Spring Security中用JWT退出登录时遇到的坑


Posted in Java/Android onOctober 16, 2021

最近有个粉丝提了个问题,说他在Spring Security中用JWT做退出登录的时无法获取当前用户,导致无法证明“我就是要退出的那个我”,业务失败!经过我一番排查找到了原因,而且这个错误包括我自己的大部分人都犯过。

Session会话

之所以要说Session会话,是因为Spring Security默认配置就是有会话的,所以当你登录以后Session就会由服务端保持直到你退出登录。只要Session保持住,你的请求只要进入服务器就可以从 ServletRequest 中获取到当前的 HttpSession ,然后会根据 HttpSession 来加载当前的 SecurityContext 。相关的逻辑在Spring Security默认的过滤器 SecurityContextPersistenceFilter 中,有兴趣可以看相关的源码。

而且默认情况下 SecurityContextPersistenceFilter 的优先级是高于退出过滤器 LogoutFilter 的,所以能够保证有Session会话的情况下退出一定能够获取当前用户。

无Session会话

使用了JWT后,每次请求都要携带 Bearer Token 并且被专门的过滤器拦截解析之后才能将用户认证信息保存到 SecurityContext 中去。参考Spring Security实战干货教程中的Token认证实现 JwtAuthenticationFilter ,相关逻辑为:

// 当token匹配         
if (jwtToken.equals(accessToken)) {
    // 解析 权限集合  这里
    JSONArray jsonArray = jsonObject.getJSONArray("roles");
    List<String> roles = jsonArray.toList(String.class);
    String[] roleArr = roles.toArray(new String[0]);

    List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(roleArr);
    User user = new User(username, "[PROTECTED]", authorities);
    // 构建用户认证token
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null, authorities);
    usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
    // 放入安全上下文中
    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
} else {
    // token 不匹配
    if (log.isDebugEnabled()){
        log.debug("token : {}  is  not in matched", jwtToken);
    }
    throw new BadCredentialsException("token is not matched");
}

为什么退出登录无法获取当前用户

分析了两种情况下用户认证信息的安全上下文配置后,我们回到问题的本身。来看看为什么用JWT会出现无法获取当前认证信息的原因。在 HttpSecurity 中,那位同学是这样配置 JwtAuthenticationFilter 的顺序的:

httpSecurity.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
我们再看看 Spring Security 过滤器排序图:

Spring Security中用JWT退出登录时遇到的坑

也就说LogoutFilter执行退出的时候,JWT还没有被 JwtAuthenticationFilter 拦截,当然无法获取当前认证上下文 SecurityContext 。

解决方法

解决方法就是必须在 LogoutFilter 执行前去解析JWT并将成功认证的信息存到 SecurityContext 。我们可以这样配置:

httpSecurity.addFilterBefore(jwtAuthenticationFilter, LogoutFilter.class)
这样问题就解决了,你只要实现把当前JWT作废掉就退出登录了。

到此这篇关于Spring Security中用JWT退出登录时遇到的坑的文章就介绍到这了,更多相关Spring Security JWT退出登录内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
基于Java的MathML转图片的方法(示例代码)
Jun 23 Java/Android
java实现对Hadoop的操作
Jul 01 Java/Android
SpringBoot快速入门详解
Jul 21 Java/Android
java设计模式--建造者模式详解
Jul 21 Java/Android
SpringBoot整合RabbitMQ的5种模式实战
Aug 02 Java/Android
SpringBoot整合阿里云视频点播的过程详解
Dec 06 Java/Android
Java如何实现通过键盘输入一个数组
Feb 15 Java/Android
Java练习之潜艇小游戏的实现
Mar 16 Java/Android
Java 获取Word中所有的插入和删除修订的方法
Apr 06 Java/Android
Spring Cloud Netflix 套件中的负载均衡组件 Ribbon
Apr 13 Java/Android
ConditionalOnProperty配置swagger不生效问题及解决
Jun 14 Java/Android
java中如何截取字符串最后一位
Jul 07 Java/Android
Java实现房屋出租系统详解
Oct 05 #Java/Android
Java Spring 控制反转(IOC)容器详解
Java spring定时任务详解
JAVA API 实用类 String详解
Oct 05 #Java/Android
SpringCloud之@FeignClient()注解的使用方式
Sep 25 #Java/Android
springboot中rabbitmq实现消息可靠性机制详解
Sep 25 #Java/Android
Spring Cloud 中@FeignClient注解中的contextId属性详解
Sep 25 #Java/Android
You might like
php 自定义错误日志实例详解
2016/11/12 PHP
用JQuery 实现的自定义对话框
2007/03/24 Javascript
Prototype Class对象学习
2009/07/19 Javascript
使用jQuery全局事件ajaxStart为特定请求实现提示效果的代码
2010/12/30 Javascript
DWR实现模拟Google搜索效果实现原理及代码
2013/01/30 Javascript
Knockout visible绑定使用方法
2013/11/15 Javascript
JavaScript将页面表格导出为Excel的具体实现
2013/12/27 Javascript
jquery实现input输入框实时输入触发事件代码
2014/01/28 Javascript
NodeJS中利用Promise来封装异步函数
2015/02/25 NodeJs
javascript中日期函数new Date()的浏览器兼容性问题
2015/09/05 Javascript
举例讲解JavaScript中将数组元素转换为字符串的方法
2015/10/25 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
跨域资源共享 CORS 详解
2016/04/26 Javascript
Ajax验证用户名或昵称是否已被注册
2017/04/05 Javascript
Vue.js 2.0学习教程之从基础到组件详解
2017/04/24 Javascript
基于JS实现移动端左滑删除功能
2017/07/28 Javascript
vue.js整合mint-ui里的轮播图实例代码
2017/12/27 Javascript
Vue中props的使用详解
2018/06/15 Javascript
JS调用安卓手机摄像头扫描二维码
2018/10/16 Javascript
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
vue.js实现简单购物车功能
2020/05/30 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
[03:37]2016完美“圣”典 风云人物:Mikasa专访
2016/12/07 DOTA
python中zip和unzip数据的方法
2015/05/27 Python
Python数据报表之Excel操作模块用法分析
2019/03/11 Python
用python介绍4种常用的单链表翻转的方法小结
2020/02/24 Python
Python关于拓扑排序知识点讲解
2021/01/04 Python
如何用Python提取10000份log中的产品信息
2021/01/14 Python
详解tf.device()指定tensorflow运行的GPU或CPU设备实现
2021/02/20 Python
CK巴西官方网站:Calvin Klein巴西
2019/07/19 全球购物
德国婴儿服装和婴儿用品购买网站:Baby Sweets
2019/12/08 全球购物
致标枪运动员加油稿
2014/02/15 职场文书
小学作文评语大全
2014/04/21 职场文书
我的梦想演讲稿
2014/04/30 职场文书
大学生受助感言
2015/08/01 职场文书
小学五年级(说明文3篇)
2019/08/13 职场文书