Spring Boot 3.0 CORS配置失效问题排查与解决咨询
Spring Boot 3.0 + Spring Security CORS配置不生效问题解决
问题现象
在Spring Boot 3.0项目中配置CORS策略后未生效:
- 初始配置下,请求响应头缺失
Access-Control-Allow-Origin字段,响应头信息如下:
* Mark bundle as not supporting multiuse < HTTP/1.1 200 < X-Content-Type-Options: nosniff < X-XSS-Protection: 0 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Frame-Options: DENY < Content-Type: application/json < Transfer-Encoding: chunked < Date: Mon, 13 Feb 2023 10:33:36 GMT
- 尝试通过
http.cors().configurationSource(corsConfigurationSource())启用CORS后,出现403错误响应:
* Mark bundle as not supporting multiuse < HTTP/1.1 403 < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < X-Content-Type-Options: nosniff < X-XSS-Protection: 0 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Frame-Options: DENY < Transfer-Encoding: chunked < Date: Mon, 13 Feb 2023 12:46:25 GMT
- 即使请求成功,响应头仍未返回期望的
Access-Control-Allow-Origin: *:
Mark bundle as not supporting multiuse < HTTP/1.1 200 < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Allow: GET,HEAD,OPTIONS < Accept-Patch: < X-Content-Type-Options: nosniff < X-XSS-Protection: 0 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Frame-Options: DENY < Content-Length: 0 < Date: Mon, 13 Feb 2023 13:28:44 GMT
原因分析
- 初始配置直接禁用CORS:原代码中
http.csrf().disable().cors().disable()完全关闭了Spring Security的CORS处理逻辑,导致自定义CORS配置无法生效。 - CORS配置未包含预检请求方法:自定义CORS仅允许
GET方法,未覆盖浏览器预检请求必需的OPTIONS方法,导致预检请求被拦截触发403。 - 过滤器顺序问题:CORS配置的执行顺序晚于权限校验,导致OPTIONS请求未被正确放行。
解决方案
步骤1:修改SecurityFilterChain配置,启用自定义CORS源
删除.cors().disable(),将CORS配置放在权限校验之前,确保过滤器优先级正确:
@Bean public SecurityFilterChain filterChain(HttpSecurity http, Jwt2AuthenticationConverter authenticationConverter, ServerProperties serverProperties) throws Exception { // 优先配置CORS,关联自定义配置源 http.cors().configurationSource(corsConfigurationSource()); http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(authenticationConverter); http.anonymous(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.csrf().disable(); // 仅保留CSRF禁用 http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> { response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\""); response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase()); }); if (serverProperties.getSsl() != null && serverProperties.getSsl().isEnabled()) { http.requiresChannel().anyRequest().requiresSecure(); } else { http.requiresChannel().anyRequest().requiresInsecure(); } http.authorizeRequests() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll() .requestMatchers(HttpMethod.GET, "/attributes/questions", "/attr-values/recent-values", "/attr-values/history") .hasAuthority("default-roles-ai-solutions") .requestMatchers(HttpMethod.POST, "/attr-values/save-attr-values") .hasAuthority("default-roles-ai-solutions") .anyRequest().authenticated() .and().oauth2ResourceServer().jwt(); return http.build(); }
步骤2:更新CORS配置,添加OPTIONS方法
修改CORS配置,确保允许的方法包含预检请求必需的OPTIONS:
@Bean CorsConfigurationSource corsConfigurationSource() { final var configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); // 添加OPTIONS方法,支持浏览器预检请求 configuration.setAllowedMethods(Arrays.asList("GET", "OPTIONS")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setExposedHeaders(Arrays.asList("*")); // 如需允许带凭证的请求,可开启此配置(不需要则删除) configuration.setAllowCredentials(true); final var source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
步骤3:验证生效
重启项目后发送请求,响应头将包含Access-Control-Allow-Origin: *,OPTIONS预检请求也会返回正常的200状态。
内容的提问来源于stack exchange,提问作者nicepeopleproject
相关产品推荐
相关产品推荐

