SpringSecurity和Flux同时使用报未认证问题

问题描述

当在项目中使用SpringSecurity时,如果controller层返回的是flux的流,那么前端请求就会抛出AuthorizationDeniedException异常。

一开始断点调试只是发现AuthorizationFilter过滤器走了两次,第一次正常通过然后springsecurity会清理认证信息导致第二次走过滤器时被判定为未认证于是报错。

一开始在网上看没有有现成的解决方案,但谁知找了五六个都要开会员,于是一怒之下怒了一下,分享出来。

报错原理

正常的springmvc流程应该是:请求-> 过滤器 -> DispatcherServlet -> 执行目标方法 -> 返回->清理SpringSecurity认证缓存

当在servlet中返回flux流式数据时流程大概是这样:请求 -> 过滤器 -> DispatcherServlet -> 执行目标方法 -> 返回flux响应并保存挂起 -> 清理SpringSecurity认证缓存 -> 数据准备好 -> 过滤器 -> DispatcherServlet -> 找到对应挂起的flux往里面塞数据 -> 前端持续接收数据

可以看到问题就出在执行目标方法只是放回流,但是流中数据还没结束。然后往流里塞数据还是得走DispatcherServlet,走servlet就会触发过滤器,就会导致认证异常。

ps: 可能有人会注意到,我的程序明明也有JWT过滤器为啥第二次不重新走JWT过滤器重新认证一遍。原因是过滤器也是有类型的,有的只处理同步请求,有的只处理异步请求,有的都可以处理,其中JWT过滤器是你自己编写的,默认只能处理同步请求,而AuthorizationFilter过滤器同步异步都会处理。

解决办法

方法一

这个方法我觉得是最简单的,就是判断如果是异步请求就不走SpringSecurity的过滤器链(应为SpringSecurity版本不同,所以可能你的配置类的属性和方法可能和我有区别,如果发现爆红,可以去把你的版本发给AI,问下AI该如何配置异步不走SpringSecurity过滤器)

java 复制代码
httpSecurity
        // 核心:忽略异步派发请求(解决二次校验)
        .securityMatcher(serverWebExchange -> {
            // 如果是 异步派发 请求 → 不进入Security过滤器
            boolean isAsync = serverWebExchange.isAsyncStarted()
                    || serverWebExchange.getDispatcherType() ==                 jakarta.servlet.DispatcherType.ASYNC;
            return !isAsync;
        })

我 自己试了一下,一共是不会影响普通方法的认证

方法二

重写AuthorizationFilter过滤器,在其中判断是否是异步请求,然后放行。

PS:如果本文的方法不可以,建议还是将你的版本和问题简单描述给AI,由AI给你答案。应为我在网上也搜了一些,要不然就是要钱要不然就是直接全部放行。

相关推荐
tntxia21 小时前
Mybatis的日志输入
java
亦暖筑序1 天前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户298698530141 天前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao1 天前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿1 天前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
鹤望兰6751 天前
字节跳动国际支付-后端开发-三面面经
java
Flittly1 天前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
RainCity1 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
doiito1 天前
【Agent Harness】Gliding Horse 的 L2 作战地图:让多 Agent 协作从“摸黑”变成“透明”
ai·rust·架构设计·系统设计·ai agent
xiezhr1 天前
逛GitHub发现一款免费带有AI功能的数据库管理工具DBX
ai·开源软件·自然语言·数据库管理工具