• Spring Security 实战干货: 登录成功后返回 JWT Token


    jwtlogin.png

    1. 前言

    欢迎阅读 Spring Security 实战干货 系列文章上一文 我们实现了 JWT 工具。本篇我们将一起探讨如何将 JWTSpring Security 结合起来,在认证成功后不再跳转到指定页面而是直接返回 JWT Token 。 本文的**DEMO 可通过文末的方式获取**

    2. 流程

    JWT 适用于前后端分离。我们在登录成功后不在跳转到首页,将会直接返回 JWT Token 对(DEMO中为JwtTokenPair),登录失败后返回认证失败相关的信息。

    3. 实现登录成功/失败返回逻辑

    如果你看过 Spring Security 实战干货: 玩转自定义登录 将非常容易理解下面的做法。

    3.1 AuthenticationSuccessHandler 返回 JWT Token

    AuthenticationSuccessHandler 用于处理登录成功后的逻辑,我们编写实现并注入 Spring IoC 容器:

         /**
          * 处理登录成功后返回 JWT Token 对.
          *
          * @param jwtTokenGenerator the jwt token generator
          * @return the authentication success handler
          */
         @Bean
         public AuthenticationSuccessHandler authenticationSuccessHandler(JwtTokenGenerator jwtTokenGenerator) {
             return (request, response, authentication) -> {
                 if (response.isCommitted()) {
                     log.debug("Response has already been committed");
                     return;
                 }
                 Map<String, Object> map = new HashMap<>(5);
                 map.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                 map.put("flag", "success_login");
                 User principal = (User) authentication.getPrincipal();
     
                 String username = principal.getUsername();
                 Collection<GrantedAuthority> authorities = principal.getAuthorities();
                 Set<String> roles = new HashSet<>();
                 if (CollectionUtil.isNotEmpty(authorities)) {
                     for (GrantedAuthority authority : authorities) {
                         String roleName = authority.getAuthority();
                         roles.add(roleName);
                     }
                 }
     
                 JwtTokenPair jwtTokenPair = jwtTokenGenerator.jwtTokenPair(username, roles, null);
     
                 map.put("access_token", jwtTokenPair.getAccessToken());
                 map.put("refresh_token", jwtTokenPair.getRefreshToken());
     
                 ResponseUtil.responseJsonWriter(response, RestBody.okData(map, "登录成功"));
             };
         }
    

    3.2 AuthenticationFailureHandler 返回认证失败信息

    AuthenticationFailureHandler 处理认证失败后的逻辑,前端根据此返回进行跳转处理逻辑,我们也实现它并注入 Spring IoC 容器:

        /**
         * 失败登录处理器 处理登录失败后的逻辑 登录失败返回信息 以此为依据跳转
         *
         * @return the authentication failure handler
         */
        @Bean
        public AuthenticationFailureHandler authenticationFailureHandler() {
            return (request, response, exception) -> {
                if (response.isCommitted()) {
                    log.debug("Response has already been committed");
                    return;
                }
                Map<String, Object> map = new HashMap<>(2);
    
                map.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                map.put("flag", "failure_login");
                ResponseUtil.responseJsonWriter(response, RestBody.build(HttpStatus.UNAUTHORIZED.value(), map, "认证失败","-9999"));
            };
        } 
    

    4. 配置

    把上面写好的两个 Handler Bean 写入 登录配置,相关片断如下,详情参见文末 DEMO:

     httpSecurity.formLogin().loginProcessingUrl(LOGIN_PROCESSING_URL).successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler)
    

    5. 验证

    我们依然通过 Spring Security 实战干货: 玩转自定义登录 一文中章节 6.4 测试 来运行。结果如下:

    5.1 登录成功结果

     {
         "httpStatus": 200,
         "data": {
             "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGwiLCJhdWQiOiJGZWxvcmRjbiIsInJvbGVzIjoiW10iLCJpc3MiOiJmZWxvcmQuY24iLCJleHAiOiIyMDE5LTExLTI3IDExOjMxOjMyIiwiaWF0IjoiMjAxOS0xMC0yOCAxMTozMTozMiIsImp0aSI6IjdmYTBlOWFiYjk5OTRjZGRhNGM5NjI4YzExNGM3YTk4In0.PvVsc8w10_0C5UIifJS1S5dEia5PQoVc_6wMfLAZOf574kt-VopHBVEp2zkjC1CNN3ltchy5rx6samaBDQvqWgoeFLXbRgNOa9Qhdf0wMLf-pUqoKRHuhBZV9HsvXSyQCFjZWlIguv4FSPZhbEff6D_8QUXmdWjlF_XEG2BPMr4",
             "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGwiLCJhdWQiOiJGZWxvcmRjbiIsInJvbGVzIjoiW10iLCJpc3MiOiJmZWxvcmQuY24iLCJleHAiOiIyMDIwLTAxLTI2IDExOjMxOjMyIiwiaWF0IjoiMjAxOS0xMC0yOCAxMTozMTozMiIsImp0aSI6IjdmYTBlOWFiYjk5OTRjZGRhNGM5NjI4YzExNGM3YTk4In0.Caj4AAothdUwZAFl8IjcAZmmXHgTt76z8trVG1sf_WHZucFVcHR8FWjShhITpArsQpmokP6GBTMsCvWDl08fUVZBpOWc1CdPUAIIEdArHCFzO64HXc_DLSyg9v0C-qYfxaTlf0npL5QxpBBr9sJcyzxZF3CnpfZpAxm8WZzXG6o",
             "time": "2019-10-28 11:32:11",
             "flag": "success_login"
         },
         "msg": "登录成功",
         "identifier": ""
     }
    

    我们取 access_token 使用官网jwt.io 提供的解码功能进行解码如下:

    5.2 登录失败结果

     {
         "httpStatus": 401,
         "data": {
             "time": "2019-10-28 12:54:10",
             "flag": "failure_login"
         },
         "msg": "认证失败",
         "identifier": "-9999"
     }
    

    6. 总结

    今天我们将 JWTSpring Security 联系了起来,实现了 登录成功后返回 JWT Token 。 这仅仅是一个开始,在下一篇我们将介绍 客户端如何使用 JWT Token 、服务端如何验证 JWT Token ,敬请关注。

    文章相关的 DEMO 可通过关注公众号:Felordcn 并回复 ss06 获取。

    关注公众号:Felordcn获取更多资讯

    个人博客:https://felord.cn

  • 相关阅读:
    云计算安全概述
    快照技术
    存储可靠性技术之--备份
    存储可靠性技术之 --RAID
    存储方式
    存储技术
    CentOS安装setup
    CentOS7安装iptables防火墙
    CentOS 7.0下使用yum安装MySQL
    The APR based Apache Tomcat Native library
  • 原文地址:https://www.cnblogs.com/felordcn/p/12142526.html
Copyright © 2020-2023  润新知