Spring Gateway集成Spring Security后OPTIONS正常但POST请求403问题排查
问题分析与解决方案
你的问题核心出在Spring Security的CSRF防护和CORS配置的执行顺序上,具体原因和修复方案如下:
问题根源
- CSRF拦截:Spring Security默认启用CSRF防护,跨域的POST请求如果没有携带CSRF Token,会直接被拦截返回403。
- CORS配置顺序错误:你自定义的
WebFilter执行顺序在Spring Security过滤器之后,当POST请求被Security拦截时,CORS响应头还未被添加,导致前端看不到相关头信息。
修复步骤
1. 修改Spring Security配置,整合CORS并关闭CSRF
删除原有的CustomCorsConfiguration类,修改SpringSecurityConfig如下:
@Configuration public class SpringSecurityConfig { @Bean SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception { http // 启用Spring Security内置的CORS处理,保证顺序优先 .cors(withDefaults()) // 网关场景下无需CSRF防护,直接关闭 .csrf().disable() .authorizeExchange(exchanges -> exchanges .pathMatchers(HttpMethod.OPTIONS, "/account/**").permitAll() .pathMatchers(HttpMethod.POST, "/account/**").permitAll() // 根据实际业务需求配置其他路径的授权规则,比如其他请求需认证 .anyExchange().authenticated() ); return http.build(); } // 配置全局CORS规则 @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 指定允许的跨域源 configuration.setAllowedOrigins(Collections.singletonList("http://localhost:4200")); // 指定允许的请求方法 configuration.setAllowedMethods(Arrays.asList("GET", "PUT", "POST", "DELETE", "OPTIONS", "PATCH")); // 指定允许的请求头 configuration.setAllowedHeaders(Arrays.asList("x-requested-with", "authorization", "Content-Type", "Content-Length", "credential", "X-XSRF-TOKEN")); // 预检请求缓存时长 configuration.setMaxAge(7200L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); // 对所有路径应用CORS规则 source.registerCorsConfiguration("/**", configuration); return source; } }
2. 为什么这样修改?
- 关闭CSRF:API网关作为后端服务的入口,CSRF防护应该由具体的业务服务来处理,网关层面关闭可以避免跨域POST请求被拦截。
- 使用Spring Security内置CORS:内置的CORS过滤器执行顺序优先于Security的认证过滤器,能确保即使请求被拦截,CORS响应头也会被正确添加;同时统一配置更易于维护。
验证
修改后重启服务,跨域POST请求应该能正常通过,响应头会包含你配置的Access-Control-Allow-Origin等CORS相关字段。
内容的提问来源于stack exchange,提问作者user3859651
相关产品推荐
相关产品推荐

