fix(webmvc): SaInterceptor 在 ASYNC 收尾派发上不再重复鉴权 - #978
Open
Rainmemery wants to merge 1 commit into
Open
Rainmemery wants to merge 1 commit into
Rainmemery wants to merge 1 commit into
Conversation
1.46.0 将上下文过滤器注册为 REQUEST+ASYNC 后(dromara#963),Spring MVC 异步请求的收尾派发会再次执行 applyPreHandle,SaInterceptor 于是对同一请求第二次执行注解鉴权。此时响应通常已提交(SSE/StreamingResponseBody 长流),token 失效抛出的 NotLoginException 无法转为错误响应,容器只能中止连接,客户端丢失整条流。 preHandle 现在对 DispatcherType.ASYNC 且 WebAsyncManager 已持有并发结果的派发直接放行;跨资源 ASYNC 派发(如 AsyncContext.dispatch("/other"),无并发结果)仍正常鉴权,避免越权。 Closes dromara#967
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #967
问题
1.46.0(7c986649)将上下文过滤器注册为 REQUEST+ASYNC 后(#963 的修复),Spring MVC 异步请求的收尾派发会再次执行
DispatcherServlet#applyPreHandle,SaInterceptor于是对同一请求第二次执行注解鉴权。此时响应通常已经 committed(SSE /StreamingResponseBody长流场景,AI 流式输出可以持续几分钟):StpUtil.checkLogin抛出NotLoginException;upstream prematurely closed connection。这次重复鉴权并不能提供额外安全性——数据在首段鉴权通过后就已经开始下发了。
修复
SaInterceptor.preHandle(sa-token-spring-boot-webmvc-v3v4-common)对满足以下条件的派发直接放行:hasConcurrentResult()为 false 的跨资源 ASYNC 派发(如AsyncContext.dispatch("/other/path"),目标 handler 的鉴权注解必须执行)不受影响,避免放宽条件导致越权;测试
sa-token-integration-boot4新增AsyncDispatchAuthTest(@SaCheckLogin+DeferredResult异步端点,MockMvcasyncDispatch走真实的 ASYNC 收尾派发路径):asyncCompletionDispatch_shouldNotReAuthAfterTokenLogout— 流进行期间StpUtil.logoutByTokenValue(token)后,收尾派发正常完成响应(修复前该用例失败,即 issue 中的连接中止现象);asyncCompletionDispatch_shouldPassWithValidToken— token 有效时收尾派发正常;initialDispatch_shouldStillRequireLogin— 初始 REQUEST 派发鉴权不受影响,未登录仍返回 401。验证过程(Ubuntu 22.04 + JDK 17 + Maven):
SaInterceptor,reactor 构建):Tests run: 3, Failures: 1— 用例 1 失败,复现 issue 场景;Tests run: 3, Failures: 0;sa-token-integration-boot4Tests run: 19, Failures: 0, Errors: 0。