配置Spring Boot CORS后仍报错,Angular跨域请求受阻如何解决?
解决Spring Boot + Angular的CORS跨域问题
报错信息
跨源请求被阻止:同源策略不允许读取位于http://localhost:8082/api/countries的远程资源。 Access to XMLHttpRequest at 'http://localhost:8082/api/countries' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. checkout.component.ts:153 GET http://localhost:8082/api/countries net::ERR_FAILED
问题背景
后端基于Spring Boot,已配置:
- 优先级最高的
CorsFilterBean,允许源为http://localhost:4200 - 引入
spring-boot-starter-data-rest依赖 CountryRepository添加@CrossOrigin注解RestAppConfig配置CorsRegistry
前端使用Angular 15:
- Checkout组件的
ngOnInit中调用FormService.getCountries请求接口 - 配置
AuthInterceptor为请求添加Authorization头
以下是具体排查和解决步骤:
1. 修正CorsFilter配置,覆盖预请求
确保CorsFilter完整覆盖预请求(OPTIONS),并包含必要的响应头:
@Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // Spring Boot 2.4+推荐使用集合形式或origin pattern config.setAllowedOrigins(Collections.singletonList("http://localhost:4200")); // 允许所有请求方法,包括OPTIONS config.addAllowedMethod("*"); // 允许Authorization等自定义请求头 config.addAllowedHeader("*"); // 暴露前端需要读取的响应头 config.addExposedHeader("Authorization"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); }
2. 移除冲突的跨域配置
多个跨域配置会互相干扰,建议只保留一种配置方式:
- 暂时注释
CountryRepository上的@CrossOrigin注解 - 停用
RestAppConfig中的CorsRegistry配置 - 优先保证
CorsFilter的唯一性,因为它的优先级高于Data REST的默认配置
3. 放行OPTIONS预请求(若有Spring Security)
带Authorization头的请求会触发OPTIONS预请求,必须确保该请求无需认证:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() .authorizeRequests() // 放行所有OPTIONS请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() .anyRequest().authenticated(); }
4. 修正Angular拦截器逻辑
拦截器需跳过OPTIONS请求,避免手动添加头导致预请求失败:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 预请求由浏览器自动处理,无需添加Authorization头 if (request.method === 'OPTIONS') { return next.handle(request); } const authToken = localStorage.getItem('authToken'); if (authToken) { request = request.clone({ setHeaders: { Authorization: `Bearer ${authToken}` } }); } return next.handle(request); }
5. 清除浏览器缓存
浏览器可能缓存旧的CORS错误响应,使用无痕模式或清除缓存后重新测试。
内容的提问来源于stack exchange,提问作者Kaushik Bhadra
相关产品推荐
相关产品推荐

