前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 实战干货:登录成功后返回 JWT Token

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

作者头像
码农小胖哥
发布2019-12-10 17:07:27
2.4K0
发布2019-12-10 17:07:27
举报

1. 前言

欢迎阅读 Spring Security 实战干货 系列文章,上一文 我们实现了 JWT 工具。本篇我们将一起探讨如何将 JWT 与 Spring 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. 总结

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 流程
  • 3. 实现登录成功/失败返回逻辑
    • 3.1 AuthenticationSuccessHandler 返回 JWT Token
      • 3.2 AuthenticationFailureHandler 返回认证失败信息
      • 4. 配置
      • 5. 验证
        • 5.1 登录成功结果
          • 5.2 登录失败结果
          • 6. 总结
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档