美文网首页springOauth2java汇集
springcloud-sso单点登陆(三)

springcloud-sso单点登陆(三)

作者: 凌康ACG | 来源:发表于2020-03-15 04:10 被阅读0次

    单点登陆的实现方式有多种:
    1、基于cas来做
    2、spring cloud oauth2的spring全家桶
    3、自定义jwt(不推荐)
    下面我们基于spring全家桶来做一个单点登陆系统2019年12月23日最新springboot版本2.2.2.RELEASE;由于篇幅问题,我们分成两篇文章。
    基于上一篇https://www.jianshu.com/p/80b125ea8e76
    源码:https://github.com/xcocean/spring-cloud-sso
    第三篇是对springcloud-sso的额外补充

    前言

    关于springcloud中的异常,可以在网关中处理,也可以在当前服务中拦截处理,返回统一结果。推荐既在网关中处理,也在元服务中处理。

    1、token自定义key

    oauth2默认的token生成是UUID,使用jwt一大推又不好,所以我们自定义登陆成功生成的access_token。自定义TokenEnhancer即可。

    CustomTokenEnhancer.java
    import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
    import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
    import org.springframework.security.oauth2.common.OAuth2AccessToken;
    import org.springframework.security.oauth2.common.OAuth2RefreshToken;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.security.oauth2.provider.token.TokenEnhancer;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class CustomTokenEnhancer implements TokenEnhancer {
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
                                         OAuth2Authentication authentication) {
            if (accessToken instanceof DefaultOAuth2AccessToken) {
                DefaultOAuth2AccessToken token = ((DefaultOAuth2AccessToken) accessToken);
                //自定义自己的 access_token
                token.setValue(customToken());
                OAuth2RefreshToken refreshToken = token.getRefreshToken();
                if (refreshToken instanceof DefaultOAuth2RefreshToken) {
                    //自定义生成的 refreshToken
                    token.setRefreshToken(new DefaultOAuth2RefreshToken(customRefreshToken()));
                }
                Map<String, Object> additionalInformation = new HashMap<String, Object>();
                additionalInformation.put("client_id", authentication.getOAuth2Request().getClientId());
                token.setAdditionalInformation(additionalInformation);
                return token;
            }
            return accessToken;
        }
    
        private static int i = 0;
        private static int j = 0;
    
        /**
         * 自定义token的值
         * 集群的时候注意不要生成重复的值即可
         */
        private String customToken() {
            i = i + 1;
            return "666" + i;
        }
    
        /**
         * 自定义token的值
         * 集群的时候注意不要生成重复的值即可
         */
        private String customRefreshToken() {
            j = j + 1;
            return "888" + i;
        }
    }
    
    AuthorizationServerConfiguration.java中注入
         // 注入自定义令牌生成
        @Bean
        public TokenEnhancer tokenEnhancer() {
            return new CustomTokenEnhancer();
        }
        // ...
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    // 用于支持密码模式
                    .authenticationManager(authenticationManager)
                    .tokenStore(tokenStore())
                    // 自定义token生成规则
                    .tokenEnhancer(tokenEnhancer())
                    .userDetailsService(userDetailsService);
        }
    

    效果如下:


    image.png

    2、刷新令牌

    刷新令牌的原理是再次调用登陆UserDetailsService需要授权注入。在上一篇文章中讲到的AuthorizationServerConfiguration.java中注入我们自定义的UserDetailsServiceImpl

        // 我们自定义的登陆UserDetailsService
        @Autowired
        private UserDetailsServiceImpl userDetailsService;
    // .....
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    // 用于支持密码模式
                    .authenticationManager(authenticationManager)
                    .tokenStore(tokenStore())
                    // 此处注入我们自定义的userDetailsService用于token的刷新
                    .userDetailsService(userDetailsService);
        }
    

    如果想刷新令牌,还是调用获取token的url,只需将grant_type换成refresh_token,post请求如下:

    http://localhost:9000/oauth/token
    参数:
    refresh_token:49eb4217-062f-47bc-956a-5d3f4684418a
    client_id:client
    client_secret:secret
    grant_type:refresh_token
    

    结果如下:


    image.png

    3、注销的实现

    注销直接调用consumerTokenServices.revokeToken(token)即可,该注销将把tokenrefresh_token一并移除掉,可观察redis的值。

        @Autowired
        private ConsumerTokenServices consumerTokenServices;
    
        @GetMapping("/user/logout")
        public ResponseResult<Void> logout(HttpServletRequest request) {
            // 获取 token
            String token = request.getParameter("access_token");
            if (token == null) {
                token = request.getHeader("authorization").split(" ")[1];
            }
            // 删除 token 以注销
            consumerTokenServices.revokeToken(token);
            return new ResponseResult<Void>(CodeStatus.OK, "用户已注销");
        }
    

    然后GET调用:http://localhost:8080/user/logout?access_token=7ed1b398-6db5-477b-80e7-783de1bf72d7

    image.png

    4、检查令牌是否有效

    直接Get访问即可:http://localhost:9000/oauth/check_token?token=2580d87d-f162-4f19-8a8f-238a4f91ae54

    image.png
    无效时:
    image.png

    相关文章

      网友评论

        本文标题:springcloud-sso单点登陆(三)

        本文链接:https://www.haomeiwen.com/subject/nbdzshtx.html