From 90eeae51af7d5366bb81f37707b2c60305af6bbc Mon Sep 17 00:00:00 2001 From: handsomeAq Date: Wed, 23 Sep 2026 17:18:11 +0800 Subject: [PATCH] =?UTF-8?q?AI=E6=8E=A5=E5=85=A5=20v0.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/accounting/config/SecurityConfig.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/com/accounting/config/SecurityConfig.java b/src/main/java/com/accounting/config/SecurityConfig.java index fdf9935..f4a5cf1 100644 --- a/src/main/java/com/accounting/config/SecurityConfig.java +++ b/src/main/java/com/accounting/config/SecurityConfig.java @@ -34,6 +34,22 @@ public class SecurityConfig { .cors(cors -> cors.configurationSource(corsConfigurationSource())) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth + // 授权只做一次,异步/错误派发不再重复鉴权。 + // + // 背景:Spring Security 6 默认 filterAllDispatcherTypes = true, + // 连 ASYNC(异步派发)和 ERROR(错误页派发)也要过 AuthorizationFilter。 + // 而这两种派发发生时 SecurityContextHolder 里已经没东西了(过滤器跳过了 + // 它们),于是被判定成匿名 → AccessDenied。 + // + // 对普通接口这只是多打一行日志,但对 SSE 是致命的:/api/ai/chat 用 + // SseEmitter,emitter.complete() 会触发一次 ASYNC 派发,此时响应早已 + // 提交,Spring 写不了错误页,就抛出 + // 「Unable to handle the Spring Security Exception because the response + // is already committed」,客户端拿到的流被异常截断。 + // + // 关掉它是安全的:ASYNC/ERROR 都不是攻击者能凭空构造的派发类型, + // 它们只是「已经通过鉴权的那次请求」的收尾阶段。 + .shouldFilterAllDispatcherTypes(false) .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/gold-price/**").permitAll() .requestMatchers("/doc.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**").permitAll()