Spring Boot升级后服务间多文件上传POST请求CSRF校验403问题求助
问题:Spring Boot升级后服务间多文件上传POST请求返回403(CSRF验证失败)
将Spring Boot应用从2.5.14版本升级至3.5.5版本后,服务间调用的多文件上传POST请求返回403错误。该接口无用户登录流程,且无法修改客户端服务添加CSRF Token,求解决办法。
Security日志内容
{"@timestamp":"2025-09-04T13:56:23.406-04:00","@version":"1","message":"Invoking CsrfFilter (5/10)","logger_name":"org.springframework.security.web.FilterChainProxy","thread_name":"http-nio-8080-exec-2","level":"TRACE","level_value":5000,"service_name":"threat-assessment","log_type":"APPLICATION"} {"@timestamp":"2025-09-04T13:56:23.407-04:00","@version":"1","message":"Wrote a CSRF token to the following request attributes: [_csrf, org.springframework.security.web.csrf.CsrfToken]","logger_name":"org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler","thread_name":"http-nio-8080-exec-2","level":"TRACE","level_value":5000,"service_name":"threat-assessment","log_type":"APPLICATION"} {"@timestamp":"2025-09-04T13:56:23.412-04:00","@version":"1","message":"Did not find a CSRF token in the [X-CSRF-TOKEN] request header","logger_name":"org.springframework.security.web.csrf.CsrfTokenRequestHandler","thread_name":"http-nio-8080-exec-2","level":"TRACE","level_value":5000,"service_name":"threat-assessment","log_type":"APPLICATION"} {"@timestamp":"2025-09-04T13:56:23.412-04:00","@version":"1","message":"Did not find a CSRF token in the [_csrf] request parameter","logger_name":"org.springframework.security.web.csrf.CsrfTokenRequestHandler","thread_name":"http-nio-8080-exec-2","level":"TRACE","level_value":5000,"service_name":"threat-assessment","log_type":"APPLICATION"} {"@timestamp":"2025-09-04T13:56:23.412-04:00","@version":"1","message":"Invalid CSRF token found for http://localhost:8080/api/v1/scans?waitFor=10","logger_name":"org.springframework.security.web.csrf.CsrfFilter","thread_name":"http-nio-8080-exec-2","level":"DEBUG","level_value":10000,"service_name":"threat-assessment","log_type":"APPLICATION"} {"@timestamp":"2025-09-04T13:56:23.412-04:00","@version":"1","message":"Responding with 403 status code","logger_name":"org.springframework.security.web.access.AccessDeniedHandlerImpl","thread_name":"http-nio-8080-exec-2","level":"DEBUG","level_value":10000,"service_name":"threat-assessment","log_type":"APPLICATION"}
当前SecurityFilterChain配置代码
@Bean public SecurityFilterChain filterChain(HttpSecurity http ) throws Exception { if(!iamProperties.isSecured()) { http .cors(Customizer.withDefaults()) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorize -> authorize .requestMatchers("/actuator/**", "/system/v1/resources").permitAll() .anyRequest().access(hasScope(SCAN_SCOPE)) ) .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults())); } return http.build(); }
解决方案
1. 检查CSRF禁用逻辑是否生效
从日志可见CsrfFilter正在执行,说明iamProperties.isSecured()的值为true,导致你的CSRF禁用代码块未被执行。先确认该配置项是否符合预期:
- 若服务间接口不需要OAuth2保护,可调整配置让
iamProperties.isSecured()为false,确保CSRF全局禁用。 - 若必须开启
isSecured,则需单独配置CSRF豁免规则。
2. 针对服务间接口豁免CSRF验证
如果无法全局禁用CSRF,可直接指定服务间调用的接口路径跳过CSRF检查,修改后的配置如下:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(Customizer.withDefaults()) .csrf(csrf -> csrf .ignoringRequestMatchers("/api/v1/scans") // 替换为你的服务间接口路径 ) .authorizeHttpRequests(authorize -> authorize .requestMatchers("/actuator/**", "/system/v1/resources").permitAll() .anyRequest().access(hasScope(SCAN_SCOPE)) ) .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults())); return http.build(); }
- 若有多个服务间接口,可添加多个
ignoringRequestMatchers参数,或使用通配符(如/api/v1/**)匹配所有相关接口。 - 此方法仅豁免指定接口的CSRF验证,不影响其他接口的安全防护。
3. 备选方案:调整CSRF Token获取方式(仅当客户端可间接传递时适用)
如果无法豁免CSRF检查,可配置Spring Security从请求的其他位置读取Token,但由于你无法修改客户端,此方法仅在客户端能通过默认支持的方式(如Cookie)传递Token时生效,优先级低于前两种方案。
内容的提问来源于stack exchange,提问作者Fredo
相关产品推荐
相关产品推荐

