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基础之this关键字的使用
Jun 30 Java/Android
Java Kafka 消费积压监控的示例代码
Jul 01 Java/Android
java设计模式--原型模式详解
Jul 21 Java/Android
Java使用JMeter进行高并发测试
Nov 23 Java/Android
使用HttpSessionListener监听器实战
Mar 17 Java/Android
Java 垃圾回收超详细讲解记忆集和卡表
Apr 08 Java/Android
Java 超详细讲解十大排序算法面试无忧
Apr 08 Java/Android
SpringBoot 集成短信和邮件 以阿里云短信服务为例
Apr 22 Java/Android
Java存储没有重复元素的数组
Apr 29 Java/Android
Java Spring Boot请求方式与请求映射过程分析
Jun 25 Java/Android
MyBatis XPathParser解析器使用范例详解
Jul 15 Java/Android
Android移动应用开发指南之六种布局详解
Sep 23 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的中问验证码
2006/11/25 PHP
PHP微信开发之文本自动回复
2016/06/23 PHP
YII2框架中excel表格导出的方法详解
2017/07/21 PHP
PHP中有关长整数的一些操作教程
2019/09/11 PHP
PHP MVC框架中类的自动加载机制实例分析
2019/09/18 PHP
JavaScript 序列化对象实现代码
2009/12/18 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
使用ionic切换页面卡顿的解决方法
2016/12/16 Javascript
简单谈谈require模块化jquery和angular的问题
2017/06/23 jQuery
使用Fullpage插件快速开发整屏翻页的页面
2017/09/13 Javascript
javaScript canvas实现(画笔大小 颜色 橡皮的实例)
2017/11/28 Javascript
nodejs+express搭建多人聊天室步骤
2018/02/12 NodeJs
vue中添加mp3音频文件的方法
2018/03/02 Javascript
微信小程序实现图片上传功能
2018/05/28 Javascript
Vue props用法详解(小结)
2018/07/03 Javascript
angularjs 动态从后台获取下拉框的值方法
2018/08/13 Javascript
从源码里了解vue中的nextTick的使用
2018/11/22 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
利用Python中的pandas库对cdn日志进行分析详解
2017/03/07 Python
Python Socket编程之多线程聊天室
2018/07/28 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
python3使用Pillow、tesseract-ocr与pytesseract模块的图片识别的方法
2020/02/26 Python
Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)
2020/04/08 Python
英国翻新电子产品购物网站:Tech Trade
2017/12/25 全球购物
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
Conforama西班牙:您的家具、装饰和电器商店
2020/02/21 全球购物
写出一个方法实现冒泡排序
2016/07/08 面试题
机电一体化专业应届生求职信
2013/11/27 职场文书
公司企业表扬信
2014/01/11 职场文书
质量管理标语
2014/06/12 职场文书
2014大学生党员评议个人总结
2014/09/22 职场文书
群众路线剖析材料
2014/09/30 职场文书
3.15消费者权益日活动总结
2015/02/09 职场文书
在职人员跳槽求职信
2015/03/20 职场文书
创业计划书之冷饮店
2019/09/27 职场文书
python使用XPath解析数据爬取起点小说网数据
2021/04/22 Python