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 Optional<Foo>转换成List<Bar>的实例方法
Jun 20 Java/Android
Java各种比较对象的方式的对比总结
Jun 20 Java/Android
Java如何实现树的同构?
Jun 22 Java/Android
OpenCV实现反阈值二值化
Nov 17 Java/Android
SpringBoot中HttpSessionListener的简单使用方式
Mar 17 Java/Android
Spring Bean是如何初始化的详解
Mar 22 Java/Android
Java 超详细讲解数据结构中的堆的应用
Apr 02 Java/Android
Android在Sqlite3中的应用及多线程使用数据库的建议
Apr 24 Java/Android
Spring Data JPA框架Repository自定义实现
Apr 28 Java/Android
详解Android中的TimePickerView(时间选择器)的用法
Apr 30 Java/Android
利用Java连接Hadoop进行编程
Jun 28 Java/Android
SpringBoot深入分析讲解监听器模式下
Jul 15 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实现数字补零功能的2个函数介绍
2014/05/12 PHP
php生成图片验证码的方法
2016/04/15 PHP
Laravel 5.1 on SAE环境开发教程【附项目demo源码】
2016/10/09 PHP
Thinkphp开发--集成极光推送
2017/09/15 PHP
JS创建优美的页面滑动块效果 - Glider.js
2007/09/27 Javascript
在UpdatePanel内jquery easyui效果失效的解决方法
2010/04/11 Javascript
JsDom 编程小结
2011/08/09 Javascript
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
Jquery阻止事件冒泡 event.stopPropagation
2011/12/11 Javascript
html组件不可输入(只读)同时任何组件都有效
2013/04/01 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
SeaJS入门教程系列之完整示例(三)
2014/03/03 Javascript
node.js中的buffer.write方法使用说明
2014/12/10 Javascript
js+canvas简单绘制圆圈的方法
2016/01/28 Javascript
Bootstrap Modal遮罩弹出层代码分享
2016/11/21 Javascript
js实现关闭网页出现是否离开提示
2017/12/07 Javascript
Node.JS循环删除非空文件夹及子目录下的所有文件
2018/03/12 Javascript
vue使用axios上传文件(FormData)的方法
2019/04/14 Javascript
nodejs实现用户登录路由功能
2019/05/22 NodeJs
vue实现多组关键词对应高亮显示功能
2019/07/25 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
使用Python编写一个最基础的代码解释器的要点解析
2016/07/12 Python
Python实现一个服务器监听多个客户端请求
2018/04/12 Python
Python拆分大型CSV文件代码实例
2019/10/07 Python
Python生成词云的实现代码
2020/01/14 Python
python中pivot()函数基础知识点
2021/01/03 Python
HTML5 Plus 实现手机APP拍照或相册选择图片上传功能
2016/07/13 HTML / CSS
详解html5 shiv.js和respond.min.js
2018/01/24 HTML / CSS
廉价航班、机票和酒店:JustFly
2018/02/07 全球购物
毕业自荐书
2013/12/09 职场文书
党员公开承诺事项
2014/03/25 职场文书
《地震中的父与子》教学反思
2014/04/10 职场文书
留学顾问岗位职责
2014/04/14 职场文书
珍爱生命演讲稿
2014/05/10 职场文书
关于有小孩的离婚协议书
2014/10/26 职场文书
户外拓展训练感想
2015/08/07 职场文书