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 相关文章推荐
为什么在foreach循环中JAVA集合不能添加或删除元素
Jun 11 Java/Android
Spring Bean的实例化之属性注入源码剖析过程
Jun 13 Java/Android
分析Netty直接内存原理及应用
Jun 14 Java/Android
基于Java的MathML转图片的方法(示例代码)
Jun 23 Java/Android
Spring Data JPA的Audit功能审计数据库的变更
Jun 26 Java/Android
Springboot集成阿里云OSS上传文件系统教程
Jun 28 Java/Android
Java网络编程之UDP实现原理解析
Sep 04 Java/Android
Android Flutter实现图片滑动切换效果
Apr 07 Java/Android
Android Flutter实现3D动画效果示例详解
Apr 07 Java/Android
Java 定时任务技术趋势简介
May 04 Java/Android
Android Gradle 插件自定义Plugin实现注意事项
Jun 16 Java/Android
Android实现图片九宫格
Jun 28 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
2个Codeigniter文件批量上传控制器写法例子
2014/07/25 PHP
PHP实现的回溯算法示例
2017/08/15 PHP
使用PHP+MySql实现微信投票功能实例代码
2017/09/29 PHP
Centos7 Yum安装PHP7.2流程教程详解
2019/07/02 PHP
php-fpm超时时间设置request_terminate_timeout资源问题分析
2019/09/27 PHP
为Yahoo! UI Extensions Grid增加内置的可编辑器
2007/03/10 Javascript
学习ExtJS Column布局
2009/10/08 Javascript
Jquery 实现Tab效果 思路是js思路
2010/03/02 Javascript
线路分流自动智能跳转代码,自动选择最快镜像网站(js)
2011/10/31 Javascript
javascript中onclick(this)用法介绍
2013/04/19 Javascript
JS this作用域以及GET传输值过长的问题解决方法
2013/08/06 Javascript
javascript常用方法汇总
2014/12/02 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
深入理解JavaScript 参数按值传递
2017/05/24 Javascript
JS实现骰子3D旋转效果
2019/10/24 Javascript
微信小程序表单验证WxValidate的使用
2019/11/27 Javascript
Vue如何获取数据列表展示
2019/12/11 Javascript
解决vue elementUI中table里数字、字母、中文混合排序问题
2020/01/07 Javascript
Java Varargs 可变参数用法详解
2020/01/28 Javascript
vue 封装 Adminlte3组件的实现
2020/03/18 Javascript
详解Webpack4多页应用打包方案
2020/07/16 Javascript
[01:10]DOTA2亚洲邀请赛 征战号角响彻全场
2015/01/06 DOTA
[01:05]DOTA2完美大师赛趣味视频之选手教你打职业
2017/11/23 DOTA
[41:52]2018DOTA2亚洲邀请赛3月29日 小组赛A组 TNC VS OpTic
2018/03/30 DOTA
python 随机数生成的代码的详细分析
2011/05/15 Python
python socket网络编程之粘包问题详解
2018/04/28 Python
详解如何从TensorFlow的mnist数据集导出手写体数字图片
2019/08/05 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
2020/11/17 Python
Tretorn美国官网:瑞典外套和鞋类品牌,抵御风雨
2018/07/19 全球购物
Petmate品牌官方网站:宠物用品
2018/11/25 全球购物
土木工程毕业生推荐信
2013/10/28 职场文书
创业者迈进成功第一步:如何写创业计划书?
2014/03/22 职场文书
三字经教学反思
2014/04/26 职场文书
办理房产证委托书
2014/09/18 职场文书
2014年团工作总结
2014/11/27 职场文书
驳回起诉裁定书
2015/05/19 职场文书