
Spring Boot 3 默认禁用全局 CORS 自动配置,当启用 Spring Security 时,必须显式调用 .cors() 方法并配合 CorsConfiguration 才能生效;仅靠 WebMvcConfigurer 或 CorsWebFilter 无法覆盖 Security 过滤链中的预检拦截。
spring boot 3 中 jwt 认证下 cors 配置失效的解决方案:spring boot 3 默认禁用全局 cors 自动配置,当启用 spring security 时,必须显式调用 `.cors()` 方法并配合 corsconfiguration 才能生效;仅靠 `webmvcconfigurer` 或 `corswebfilter` 无法覆盖 security 过滤链中的预检拦截。
在 Spring Boot 3 + Spring Security 6 的组合中,CORS 不再由 WebMvcConfigurer 单独控制——它会被 SecurityFilterChain 的默认行为覆盖或忽略。尤其当请求携带认证凭据(如 Authorization: Bearer <token>)时,浏览器会先发送 OPTIONS 预检请求,而若 Security 配置未显式启用并配置 CORS,则该预检将被拒绝(返回 401/403),导致前端报错 CORS error,即使你的 @CrossOrigin 注解或 WebMvcConfigurer 已正确设置。
✅ 正确做法是:在 SecurityFilterChain 中显式启用并配置 CORS,而非依赖 MVC 层配置。以下是推荐的完整修复方案:
1. 移除冗余的 WebMvcConfigurer CORS 配置(可选但建议)
// ❌ 删除或注释掉此配置(避免冲突)
@Configuration
public class WebConfigCors implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}⚠️ 注意:WebMvcConfigurer#addCorsMappings 在 Security 启用后不生效于受保护端点,仅对未被 Security 拦截的静态资源或 /actuator 等路径有效。
2. 在 SecurityFilterChain 中启用并配置 CORS
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// ✅ 关键:启用 CORS 并关联配置
http
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // ← 必须显式配置
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authz -> authz
.requestMatchers(
"/api/v1/account/register",
"/api/v1/account/password-recovery/**",
"/api/v1/account/authenticate",
"/api/v1/account/emailValidation/**",
"/api/v1/questions",
"/swagger-ui/**",
"/v3/api-docs/**",
"/webjars/**"
).permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
.logout(logout -> logout
.logoutUrl("/api/v1/account/logout")
.addLogoutHandler(logoutHandler)
.logoutSuccessHandler((req, res, auth) ->
SecurityContextHolder.clearContext())
);
return http.build();
}
// 提供 CORS 配置源(支持通配符与凭证)
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*")); // 生产环境请替换为具体域名,如 ["http://localhost:5173", "https://your-app.com"]
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true); // 若前端发送 credentials(如 axios with {withCredentials: true}),此项必须为 true
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}3. 前端请求示例(Axios / Fetch)
确保前端在发送带 Token 的请求时,显式携带凭据(若后端 setAllowCredentials(true)):
// Axios 示例
axios.get('/api/v1/account/profile', {
headers: { Authorization: 'Bearer YOUR_JWT_TOKEN' },
withCredentials: true // ← 必须开启(与后端 allowCredentials 一致)
});
// Fetch 示例
fetch('/api/v1/account/profile', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_JWT_TOKEN',
'Content-Type': 'application/json'
},
credentials: 'include' // ← 对应 withCredentials: true
});? 关键要点总结:
- ✅ .cors() 必须出现在 .csrf().disable() 之后、.authorizeHttpRequests() 之前;
- ✅ CorsConfigurationSource 是唯一被 SecurityFilterChain 尊重的 CORS 来源;
- ✅ 若前端使用 withCredentials: true 或 credentials: 'include',后端 setAllowCredentials(true) 且 allowedOrigins *不能为 `""** ——需指定明确域名(如["http://localhost:5173"]`),否则浏览器拒绝响应;
- ✅ JWT 认证端点失败常因预检(OPTIONS)被 Security 拦截而未放行,.cors() 可自动处理预检响应;
- ✅ @CrossOrigin 注解仍可用于单个 Controller 方法,但全局策略应统一由 Security 管理。
完成上述配置后,重启应用,认证接口即可正常响应跨域请求,不再出现 CORS error。

















