异构服务器 微服务_SpringCloud微服务实战系列(十八)Ouath2在真实场景中的应用之授权服务器...

eede05c2d33f49b70ac56b3f2ad8a8d9.png

SpringCloud微服务实战系列(十八)Ouath2在真实场景中的应用之授权服务器

一、概述

在《SpringCloud微服务实战系列(十七)Ouath2在真实场景中的应用之资源服务器》]中 已经介绍了资源服务器是如何搭建的。

本篇就是对Oauth2的实际应用方法的授权服务器搭建方式进行介绍。

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

在Spring Oauth2中,Oauth2的使用过程中将角色分为三种:ResourceServer,AuthorizationServer,OauthClient.

由于篇幅较大,这里将Oauth2的搭建分成三个部分。本篇先介绍AuthorizationServer。

二、授权服务器

授权服务器就是Oauth2的认证中心。管理token、client等,需要配置的东西很多。

下面讲述下这个过程是怎样的。

2.1 引入依赖

需要引入spring-boot-starter-web、spring-cloud-starter-security和spring-security-oauth2和mybatis相关jar包.

依赖如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>${security.oauth2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.34</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
    </dependency>
</dependencies>

这里,security.oauth2.version我选择的是2.3.5.RELEASE。

2.2 配置文件

这里使用yaml文件写配置,配置文件application.yml:

application.yml:

server:
   port: 8182
spring:
   main:
      allow-bean-definition-overriding: true
   profiles:
      active: loc
   application:
      name: oauthAuth
mybatis:
   configuration:
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这里

  1. 应用名称为oauthAuth
  2. allow-bean-definition-overriding为true,是因为要定义新的bean,覆盖默认的。

application-loc.yml:

env: loc
spring:
   datasource:
      type: org.apache.commons.dbcp2.BasicDataSource
      dbcp2:
         max-wait-millis: 60000
         min-idle: 20
         initial-size: 2
         connection-properties: characterEncoding=utf8
         validation-query: SELECT 1
         test-while-idle: true
         test-on-borrow: true
         test-on-return: false
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/boot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
      username: cff
      password: 123456

这里配置的是数据库及数据源信息

2.3 启动

使用main直接启动即可。需要使用注解@EnableAuthorizationServer表明它是授权服务器。

OauthAuthApplication:

package cn.pomit.springbootwork.oauthauth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;


@EnableAuthorizationServer
@SpringBootApplication
public class OauthAuthApplication {
    public static void main(String[] args) {
        SpringApplication.run(OauthAuthApplication.class, args);
    }
}

2.4 安全控制配置

这个安全控制,只是普通的Spring Security的安全配置。

需要继承WebSecurityConfigurerAdapter,并加上@EnableWebSecurity。

AccessSecurityConfiguration如下:

package cn.pomit.springbootwork.oauthauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import cn.pomit.springbootwork.oauthauth.handler.AjaxAuthFailHandler;
import cn.pomit.springbootwork.oauthauth.handler.AjaxLogoutSuccessHandler;
import cn.pomit.springbootwork.oauthauth.handler.AuthSuccessHandler;
import cn.pomit.springbootwork.oauthauth.handler.UnauthorizedEntryPoint;
import cn.pomit.springbootwork.oauthauth.provider.SimpleAuthenticationProvider;

@Configuration
@EnableWebSecurity
public class AccessSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private SimpleAuthenticationProvider simpleAuthenticationProvider;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(simpleAuthenticationProvider);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthorizedEntryPoint()).and()
                .csrf().disable()
                .authorizeRequests().antMatchers("/oauth/**").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/index.html").permitAll()
                .antMatchers("/css/**").permitAll()
                .antMatchers("/js/**").permitAll()
                .antMatchers("/img/**").permitAll()
                .antMatchers("/api/**").authenticated()
                .and().formLogin()
                .loginPage("/login.html").usernameParameter("userName").passwordParameter("userPwd")
                .loginProcessingUrl("/login").successHandler(new AuthSuccessHandler())
                .failureHandler(new AjaxAuthFailHandler()).and()
                .logout().logoutUrl("/logout")
                .logoutSuccessHandler(new AjaxLogoutSuccessHandler());
    }
}

其中,SimpleAuthenticationProvider是处理用户名密码校验的。

UnauthorizedEntryPoint、AuthSuccessHandler、AjaxAuthFailHandler、AjaxLogoutSuccessHandler这些是对认证成功、失败等的处理方法,后面会贴出来,这里先不细讲了。

注意: /oauth/**路径要放开

2.5 授权服务器配置

  1. 因为授权服务器默认存储的客户端信息默认都是基于内存的,然而,实际应用中都是基于数据库的,因此,我们要把它改造为数据库中获取,比如:
  2. Oauth2的授权码是6位,实在是有点短,可以重写AuthorizationCodeServices,将它变成更长位数。
  3. PasswordEncoder需要指定,如果不需要对密码进行处理,可以使用NoOpPasswordEncoder。

AuthorizationServerConfiguration:

package cn.pomit.springbootwork.oauthauth.config;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;

import cn.pomit.springbootwork.oauthauth.domain.OauthClientInfo;
import cn.pomit.springbootwork.oauthauth.service.OauthClientService;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    @Autowired
    @Qualifier("authorizationCodeServices")
    private AuthorizationCodeServices authorizationCodeServices;

    @Autowired
    OauthClientService oauthClientService;

    @Bean
    public PasswordEncoder noOpPasswordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 可以在这里将客户端数据替换成数据库配置。
     * 
     * @return
     */
    @Bean
    public ClientDetailsService clientDetailsService() {
        InMemoryClientDetailsService inMemoryClientDetailsService = new InMemoryClientDetailsService();
        Map<String, ClientDetails> clientDetailsStore = new HashMap<>();

        List<OauthClientInfo> clientList = oauthClientService.findAll();
        for (OauthClientInfo item : clientList) {
            BaseClientDetails baseClientDetails = new BaseClientDetails();
            baseClientDetails.setClientId(item.getClientId());
            baseClientDetails.setClientSecret(item.getClientSecret());
            baseClientDetails.setAccessTokenValiditySeconds(item.getAccessTokenTime());
            baseClientDetails.setRefreshTokenValiditySeconds(item.getRefreshTokenTime());

            Set<String> salesWords = new HashSet<String>(Arrays.asList(item.getRedirectUrls().split(",")));
            baseClientDetails.setRegisteredRedirectUri(salesWords);
            List<String> scope = Arrays.asList(item.getScopes().split(","));
            baseClientDetails.setScope(scope);

            List<String> authorizedGrantTypes = Arrays.asList(item.getAuthorizedGrantTypes().split(","));
            baseClientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
            clientDetailsStore.put(item.getClientId(), baseClientDetails);
        }

        inMemoryClientDetailsService.setClientDetailsStore(clientDetailsStore);

        return inMemoryClientDetailsService;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authorizationCodeServices(authorizationCodeServices);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
    }
}

2.6 授权码长度控制AuthorizationCodeServices

InMemoryAuthorizationCodeServices :

package cn.pomit.springbootwork.oauthauth.token;

import java.util.concurrent.ConcurrentHashMap;

import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
import org.springframework.stereotype.Service;

@Service("authorizationCodeServices")
public class InMemoryAuthorizationCodeServices extends RandomValueAuthorizationCodeServices {
    protected final ConcurrentHashMap<String, OAuth2Authentication> authorizationCodeStore = new ConcurrentHashMap<String, OAuth2Authentication>();
    private RandomValueStringGenerator generator = new RandomValueStringGenerator(16);

    @Override
    protected void store(String code, OAuth2Authentication authentication) {
        this.authorizationCodeStore.put(code, authentication);
    }

    @Override
    public OAuth2Authentication remove(String code) {
        OAuth2Authentication auth = this.authorizationCodeStore.remove(code);
        return auth;
    }

    @Override
    public String createAuthorizationCode(OAuth2Authentication authentication) {
        String code = generator.generate();
        store(code, authentication);
        return code;
    }
}

它和Spring的InMemoryAuthorizationCodeServices没多大区别,区别在于RandomValueStringGenerator对象构造函数参数是16。

2.7 用户密码校验

SimpleAuthenticationProvider用来控制用户的校验,属于SpringSecurity的常用写法。

SimpleAuthenticationProvider:

package cn.pomit.springbootwork.oauthauth.provider;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;

import cn.pomit.springbootwork.oauthauth.domain.UserInfo;
import cn.pomit.springbootwork.oauthauth.service.UserInfoService;

@Component
public class SimpleAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserInfoService userInfoService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        String userName = authentication.getPrincipal().toString();
        UserInfo user = userInfoService.getUserInfoByUserName(userName);

        if (user == null) {
            throw new BadCredentialsException("查无此用户");
        }
        if (user.getPasswd() != null && user.getPasswd().equals(authentication.getCredentials())) {
            Collection<? extends GrantedAuthority> authorities = null;
            if (user.getUserType() != null && user.getUserType().equals("2")) {
                authorities = AuthorityUtils
                        .createAuthorityList("ROLE_ADMIN");
            } else {
                authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
            }

            return new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPasswd(), authorities);
        } else {
            throw new BadCredentialsException("用户名或密码错误。");
        }
    }

    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }

}

2.8 Service、Mapper及一些简单的Handler

这里是我用到的一些Service、Mapper及简单的Handler,可以根据自己的需要随便改。

2.8.1 Service

OauthClientService:

package cn.pomit.springbootwork.oauthauth.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.pomit.springbootwork.oauthauth.domain.OauthClientInfo;
import cn.pomit.springbootwork.oauthauth.mapper.TOauthClientMapper;

@Service
public class OauthClientService {

    @Autowired
    TOauthClientMapper tOauthClientMapper;

    public List<OauthClientInfo> findAll() {
        return tOauthClientMapper.findAll();
    }
}

UserInfoService:

package cn.pomit.springbootwork.oauthauth.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.pomit.springbootwork.oauthauth.domain.UserInfo;
import cn.pomit.springbootwork.oauthauth.mapper.UserInfoMapper;

@Service
public class UserInfoService {
    @Autowired
    UserInfoMapper userInfoMapper;
    public UserInfo getUserInfoByUserName(String userName){
        return userInfoMapper.findByUserName(userName);
    }

    public List<UserInfo> page(int page, int size){
        return userInfoMapper.testPageSql(page, size);
    }

    public List<UserInfo> testTrimSql(UserInfo userInfo){
        return userInfoMapper.testTrimSql(userInfo);
    }
}

2.8.2 Mapper

TOauthClientMapper:

package cn.pomit.springbootwork.oauthauth.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import cn.pomit.springbootwork.oauthauth.domain.OauthClientInfo;

@Mapper
public interface TOauthClientMapper {
    @Select({
       "<script>",
            "SELECT ",
            "client_id as clientId,client_secret as clientSecret,access_token_time as accessTokenTime,refresh_token_time as refreshTokenTime,redirect_urls as redirectUrls,scopes as scopes,authorized_grant_types as authorizedGrantTypes",
            "FROM t_oauth_client",
       "</script>"})
    List<OauthClientInfo> findAll();

}

UserInfoMapper:

package cn.pomit.springbootwork.oauthauth.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import cn.pomit.springbootwork.oauthauth.domain.UserInfo;

@Mapper
public interface UserInfoMapper {
    @Select({
        "<script>",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
            "FROM user_info",
            "WHERE user_name = #{userName,jdbcType=VARCHAR}",
       "</script>"})
    UserInfo findByUserName(@Param("userName") String userName);

    @Select({
        "<script>",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
            "FROM user_info",
            "WHERE mobile = #{mobile,jdbcType=VARCHAR}",
            "<if test='userType != null and userType != "" '> and user_type = #{userType, jdbcType=VARCHAR} </if>",
       "</script>"})
    List<UserInfo> testIfSql(@Param("mobile") String mobile,@Param("userType") String userType);

    @Select({
        "<script>",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
             "     FROM user_info ",
             "    WHERE mobile IN (",
             "   <foreach collection = 'mobileList' item='mobileItem' index='index' separator=',' >",
             "      #{mobileItem}",
             "   </foreach>",
             "   )",
        "</script>"})
    List<UserInfo> testForeachSql(@Param("mobileList") List<String> mobile);

    @Update({
        "<script>",
            "   UPDATE user_info",
            "   SET ",
            "   <choose>",
            "   <when test='userType!=null'> user_type=#{user_type, jdbcType=VARCHAR} </when>",
            "   <otherwise> user_type='0000' </otherwise>",
            "   </choose>",
            "   WHERE user_name = #{userName, jdbcType=VARCHAR}",
        "</script>" })
    int testUpdateWhenSql(@Param("userName") String userName,@Param("userType") String userType);

    @Select({
        "<script>",
            "<bind name="tableName" value="item.getIdentifyTable()" />",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
            "FROM ${tableName}",
            "WHERE mobile = #{item.mobile,jdbcType=VARCHAR}",
       "</script>"})
    public List<UserInfo> testBindSql(@Param("item") UserInfo userInfo);

    @Select({
        "<script>",
            "<bind name="startNum" value="page*pageSize" />",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
            "FROM user_info",
            "ORDER BY mobile ASC",
            "LIMIT #{pageSize} OFFSET #{startNum}",
       "</script>"})
    public List<UserInfo> testPageSql(@Param("page") int page, @Param("pageSize") int size);

    @Select({
        "<script>",
            "SELECT ",
            "user_name as userName,passwd,name,mobile,valid, user_type as userType",
            "FROM user_info",
            "<trim prefix=" where " prefixOverrides="AND">",
                "<if test='item.userType != null and item.userType != "" '> and user_type = #{item.userType, jdbcType=VARCHAR} </if>",
                "<if test='item.mobile != null and item.mobile != "" '> and mobile = #{item.mobile, jdbcType=VARCHAR} </if>",
            "</trim>",
       "</script>"})
    public List<UserInfo> testTrimSql(@Param("item") UserInfo userInfo);

    @Update({
        "<script>",
            "   UPDATE user_info",
            "   <set> ",
            "<if test='item.userType != null and item.userType != "" '>user_type = #{item.userType, jdbcType=VARCHAR}, </if>",
            "<if test='item.mobile != null and item.mobile != "" '> mobile = #{item.mobile, jdbcType=VARCHAR} </if>",
            "   </set>",
            "   WHERE user_name = #{item.userName, jdbcType=VARCHAR}",
        "</script>" })
    public int testSetSql(@Param("item") UserInfo userInfo);
}

2.8.3 Handler

AjaxAuthFailHandler:

package cn.pomit.springbootwork.oauthauth.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.pomit.springbootwork.oauthauth.model.ResultCode;
import cn.pomit.springbootwork.oauthauth.model.ResultModel;

public class AjaxAuthFailHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        if (isAjaxRequest(request)) {
            ResultModel rm = new ResultModel(ResultCode.CODE_00014.getCode(), exception.getMessage());
            ObjectMapper mapper = new ObjectMapper();
            response.setStatus(HttpStatus.OK.value());
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            mapper.writeValue(response.getWriter(), rm);
        } else {
            setDefaultFailureUrl("/login.html");
            super.onAuthenticationFailure(request, response, exception);
        }
    }

    public static boolean isAjaxRequest(HttpServletRequest request) {
        String ajaxFlag = request.getHeader("X-Requested-With");
        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
    }
}

AjaxLogoutSuccessHandler:

package cn.pomit.springbootwork.oauthauth.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.pomit.springbootwork.oauthauth.model.ResultCode;
import cn.pomit.springbootwork.oauthauth.model.ResultModel;

public class AjaxLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        if (isAjaxRequest(request)) {
            ResultModel rm = new ResultModel(ResultCode.CODE_00000);
            ObjectMapper mapper = new ObjectMapper();
            response.setStatus(HttpStatus.OK.value());
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            mapper.writeValue(response.getWriter(), rm);
        } else {
            super.onLogoutSuccess(request, response, authentication);
        }
    }

    public static boolean isAjaxRequest(HttpServletRequest request) {
        String ajaxFlag = request.getHeader("X-Requested-With");
        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
    }
}

AuthSuccessHandler:

package cn.pomit.springbootwork.oauthauth.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;

public class AuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    protected final Log logger = LogFactory.getLog(this.getClass());

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
         RequestCache cache = new HttpSessionRequestCache();
         SavedRequest savedRequest = cache.getRequest(request, response);
         String url = savedRequest.getRedirectUrl();

         response.sendRedirect(url);
    }
}

UnauthorizedEntryPoint:

package cn.pomit.springbootwork.oauthauth.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.pomit.springbootwork.oauthauth.model.ResultCode;
import cn.pomit.springbootwork.oauthauth.model.ResultModel;

public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        if (isAjaxRequest(request)) {
            ResultModel rm = new ResultModel(ResultCode.CODE_40004);
            ObjectMapper mapper = new ObjectMapper();
            response.setStatus(HttpStatus.OK.value());
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            mapper.writeValue(response.getWriter(), rm);
        } else {
            response.sendRedirect("/login.html");
        }

    }

    public static boolean isAjaxRequest(HttpServletRequest request) {
        String ajaxFlag = request.getHeader("X-Requested-With");
        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
    }
}

2.8.4 实体

UserInfo:

package cn.pomit.springbootwork.oauthauth.domain;

public class UserInfo {
    private String userName;
    private String passwd;
    private String name;
    private String mobile;
    private Integer valid;
    private String userType;

    public UserInfo() {

    }

    public UserInfo(UserInfo src) {
        this.userName = src.userName;
        this.passwd = src.passwd;
        this.name = src.name;
        this.mobile = src.mobile;
        this.valid = src.valid;
    }

    public UserInfo(String userName, String passwd, String name, String mobile, Integer valid) {
        super();
        this.userName = userName;
        this.passwd = passwd;
        this.name = name;
        this.mobile = mobile;
        this.valid = valid;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMobile() {
        return mobile;
    }

    public void setValid(Integer valid) {
        this.valid = valid;
    }

    public Integer getValid() {
        return valid;
    }

    public String getUserType() {
        return userType;
    }

    public void setUserType(String userType) {
        this.userType = userType;
    }

    public String getIdentifyTable(){
        return "user_info";
    }
}

OauthClientInfo:

package cn.pomit.springbootwork.oauthauth.domain;

public class OauthClientInfo {
    private String clientId;
    private String clientSecret;
    private int accessTokenTime;
    private int refreshTokenTime;
    private String redirectUrls;
    private String scopes;

    private String authorizedGrantTypes;

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientSecret(String clientSecret) {
        this.clientSecret = clientSecret;
    }

    public String getClientSecret() {
        return clientSecret;
    }

    public void setAccessTokenTime(int accessTokenTime) {
        this.accessTokenTime = accessTokenTime;
    }

    public int getAccessTokenTime() {
        return accessTokenTime;
    }

    public void setRefreshTokenTime(int refreshTokenTime) {
        this.refreshTokenTime = refreshTokenTime;
    }

    public int getRefreshTokenTime() {
        return refreshTokenTime;
    }

    public void setRedirectUrls(String redirectUrls) {
        this.redirectUrls = redirectUrls;
    }

    public String getRedirectUrls() {
        return redirectUrls;
    }

    public void setScopes(String scopes) {
        this.scopes = scopes;
    }

    public String getScopes() {
        return scopes;
    }

    public String getAuthorizedGrantTypes() {
        return authorizedGrantTypes;
    }

    public void setAuthorizedGrantTypes(String authorizedGrantTypes) {
        this.authorizedGrantTypes = authorizedGrantTypes;
    }

}

2.9 测试web

OauthAuthRest:

package cn.pomit.springbootwork.oauthauth.web;

import java.security.Principal;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import cn.pomit.springbootwork.oauthauth.model.IpModel;
import cn.pomit.springbootwork.oauthauth.model.ResultModel;
import cn.pomit.springbootwork.oauthauth.util.IPUtil;

@RestController
@RequestMapping("/api")
public class OauthAuthRest {

    @RequestMapping(value = "/ip", method = { RequestMethod.GET })
    public ResultModel ip(HttpServletRequest request) {
        IpModel ipModel = new IpModel();
        ipModel.setClientIpAddress(IPUtil.getIpAddr(request));
        ipModel.setServerIpAddress(IPUtil.localIp());
        return ResultModel.ok(ipModel);
    }

    @RequestMapping(value = "/userInfo")
    public ResultModel userinfo(Principal principal) {

        return ResultModel.ok(principal.getName());
    }

}

OauthTestRest:

package cn.pomit.springbootwork.oauthauth.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import cn.pomit.springbootwork.oauthauth.model.ResultModel;

@Controller
@RequestMapping("/")
public class OauthTestRest {

    @ResponseBody
    @RequestMapping(value = "/test/test", method = { RequestMethod.GET })
    public ResultModel test() {

        return ResultModel.ok("我就是test");
    }

    @RequestMapping(value = "/", method = { RequestMethod.GET })
    public String index() {

        return "/index.html";
    }


    @RequestMapping(value = "/oauth/confirm_access", method = { RequestMethod.GET })
    public String oauthAuthorize() {

        return "/authorize.html";
    }
}

IPUtil:

package cn.pomit.springbootwork.oauthauth.util;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;

public class IPUtil {
    /**
     * @Description: 获取客户端IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("127.0.0.1")) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

    /**
     * 获取的是本地的IP地址
     * 
     * @return
     */
    public static String localIp() {
        String result = "";
        try {
            InetAddress address = InetAddress.getLocalHost();
            result = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return result;
    }
}

ResultModel:

package cn.pomit.springbootwork.oauthauth.model;

/**
 * @author cff
 */
public class ResultModel {
    private String errorCode;
    private String message;
    private Object data;

    public ResultModel() {

    }

    public ResultModel(String errorCode, String message) {
        this.errorCode = errorCode;
        this.message = message;
    }

    public ResultModel(String errorCode, String message, Object data) {
        this.errorCode = errorCode;
        this.message = message;
        this.data = data;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void set ErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static ResultModel ok(String testValue) {
        ResultModel rm = new ResultModel();
        rm.setData(testValue);
        return rm;
    }
}

品茗IT-博客专题:https://www.pomit.cn/lecture.html汇总了Spring专题、Springboot专题、SpringCloud专题、web基础配置专题。

快速构建项目

Spring项目快速开发工具:

一键快速构建Spring项目工具

一键快速构建SpringBoot项目工具

一键快速构建SpringCloud项目工具

一站式Springboot项目生成

Mysql一键生成Mybatis注解Mapper

Spring组件化构建

SpringBoot组件化构建

SpringCloud服务化构建

喜欢这篇文章么,喜欢就加入我们一起讨论SpringCloud使用吧!

fd9c79535155f9d7063c7a978241729d.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值