Spring Boot REST API添加Content-Security-Policy头后遇CORS问题求助
解决Spring Boot跨域预检请求失败问题
你遇到的报错是CORS策略阻止请求,根源是浏览器发起跨域请求前的OPTIONS预检请求未被服务器正确响应,和你配置的X-Content-Security-Policy响应头无关。Swagger调用正常是因为Swagger页面和API服务同域,不会触发跨域检查;而本地UI(http://localhost:4200)和API服务端口不同,属于跨域请求,浏览器会先发送OPTIONS预检请求验证服务器是否允许跨域,你的服务当前没有处理这个请求,导致报错。
方案一:全局配置CORS(推荐)
修改你的WebSecurityConfig,添加CORS配置,确保OPTIONS请求被正确处理:
@EnableWebSecurity @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // 启用CORS配置 .cors().and() // 禁用CSRF(按需调整,若业务需要CSRF可保留并配置放行规则) .csrf().disable() // 其他原有配置 .headers() .addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy","script-src 'self'")); } // 定义CORS规则 @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 允许本地UI的跨域请求,生产环境请替换为实际前端域名 config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); // 允许的HTTP请求方法 config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 允许所有请求头 config.setAllowedHeaders(Arrays.asList("*")); // 允许携带Cookie等凭证(按需开启) config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); // 对所有API路径应用CORS规则 source.registerCorsConfiguration("/**", config); return source; } }
适配Spring Boot 2.7+版本(WebSecurityConfigurerAdapter已弃用)
如果你的Spring Boot版本是2.7及以上,使用SecurityFilterChain替代WebSecurityConfigurerAdapter:
@EnableWebSecurity @Configuration public class WebSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) .headers(headers -> headers .addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy","script-src 'self'")) ); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
方案二:局部接口配置CORS
如果只需要给特定接口开启跨域,可在Controller类或方法上添加@CrossOrigin注解:
@RestController // 对当前Controller下所有接口开启跨域 @CrossOrigin(origins = "http://localhost:4200", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS}) public class YourApiController { // 接口方法 }
注意事项
- 生产环境不要使用
*作为allowedOrigins,必须指定具体的前端域名,避免安全风险。 - 如果业务需要保留CSRF防护,需确保OPTIONS预检请求能绕过CSRF校验,可添加
csrf().ignoringAntMatchers("/**")(按需调整路径)。 - 配置完成后,重启Spring Boot服务,再用本地UI测试跨域请求。
内容的提问来源于stack exchange,提问作者Rjj
相关产品推荐
相关产品推荐

