Spring Boot+React跨域返回403 配置CORS允许*仍被拦截
问题根因
返回403跨域拦截、配置的Access-Control-Allow-Origin: *不生效,是三个配置错误共同导致的:
- 你的POST请求携带了
Content-Type: application/json头,属于CORS规范里的非简单请求,浏览器会先发送OPTIONS方法的预检请求,你之前只放通了注册接口路径的OPTIONS请求,其余路径的预检请求会被Spring Security的认证链直接拦截返回403,根本到不了CORS处理器。 - CORS配置不全:仅配置了允许的源和请求方法,没有配置允许的请求头,同时高版本Spring(5.3+)中
setAllowedOrigins("*")无法兼容非简单请求、跨域携带凭证的场景,不会正确返回跨域响应头。 - 自定义JWT过滤器默认执行顺序在CORS处理器之前,预检请求不带认证token,会先被JWT认证过滤器拦截打回403。
修复步骤
1. 补全CORS配置
替换SecurityConfiguration.java中corsConfigurationSource方法的代码:
@Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); // 替换原setAllowedOrigins,使用模式匹配兼容所有源,支持后续携带凭证场景 configuration.setAllowedOriginPatterns(List.of("*")); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")); // 允许所有请求头,包含Content-Type、自定义JWT认证头等 configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); // 预检请求缓存1小时,减少重复预检请求 configuration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
2. 调整Spring Security拦截规则与过滤器顺序
修改configure(HttpSecurity http)方法的配置,全局放通所有OPTIONS预检请求,同时强制CORS过滤器在所有自定义JWT认证过滤器之前执行:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors().and().csrf().disable() .authorizeRequests() // 全局放通所有OPTIONS预检请求,必须放在授权规则最顶部 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll() .antMatchers(HttpMethod.GET, API_DOCUMENTATION_URLS).permitAll() .anyRequest().authenticated() .and() // 调整过滤器执行顺序,确保CORS处理在认证逻辑之前 .addFilterAfter(new JWTAuthenticationFilter(authenticationManager()), org.springframework.web.filter.CorsFilter.class) .addFilterAfter(new JWTAuthorizationFilter(authenticationManager()), JWTAuthenticationFilter.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); }
3. 修正JWT认证过滤器拦截路径
JWTAuthenticationFilter继承自UsernamePasswordAuthenticationFilter,默认仅拦截POST /login路径的请求,如果你的实际登录接口不是该路径,需要在构造器中手动指定:
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; // 替换为你项目实际的登录接口路径 setFilterProcessesUrl("/users/auth/login"); }
验证逻辑
修改完成后重启后端服务,重新触发注册请求:
- 浏览器控制台中OPTIONS预检请求返回200状态码,响应头携带完整的CORS相关字段
- 预检通过后实际POST注册请求正常发送,返回200状态码,不再触发跨域拦截
- Postman携带
Origin: http://localhost:3000请求头测试接口,可正常返回预期结果,不再返回403
内容的提问来源于stack exchange,提问作者anio
相关产品推荐
相关产品推荐

