Spring Boot网关配置CorsWebFilter报Access-Control-Allow-Origin多源错误求助
问题根因
你遇到的两次报错均为跨域配置的典型问题:
- 最初的
Access Control Origin header not present是因为网关没有配置跨域策略,浏览器跨域请求被拦截 - 后续的
Access-Control-Allow-Origin cannot contain more than one origin是因为响应中出现了重复的Access-Control-Allow-Origin响应头,不符合浏览器CORS规范。Postman不会校验CORS规则,所以请求正常。
解决方案
1. 修正CORS配置类
Spring Boot 2.4+版本后,直接使用addAllowedOrigin("*")在请求带认证凭证时会触发规则冲突,替换为setAllowedOriginPatterns兼容场景:
import java.util.Collections; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.reactive.CorsWebFilter; @Configuration public class CorsConfig { @Bean public CorsWebFilter corsWebFilter() { final CorsConfiguration corsConfig = new CorsConfiguration(); corsConfig.setMaxAge(3600L); // 替换原addAllowedOrigin("*"),兼容带认证信息的跨域请求 corsConfig.setAllowedOriginPatterns(Collections.singletonList("*")); corsConfig.addAllowedHeader("*"); // 开启跨域凭证传递,适配前端带Authorization头的请求场景 corsConfig.setAllowCredentials(true); corsConfig.addAllowedMethod("OPTIONS"); corsConfig.addAllowedMethod("HEAD"); corsConfig.addAllowedMethod("GET"); corsConfig.addAllowedMethod("PUT"); corsConfig.addAllowedMethod("POST"); corsConfig.addAllowedMethod("DELETE"); corsConfig.addAllowedMethod("PATCH"); final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig); return new CorsWebFilter(source); } }
2. 网关路由添加响应头去重配置
在所有路由的过滤器中添加CORS响应头去重规则,避免多链路写入重复头:
@Bean public RouteLocator routes(RouteLocatorBuilder builder) { String authorizationValue = getAuthorization(); return builder.routes() .route("auth-service", r -> r.path("/auth-service/**") .filters(f -> f.filter(filter) // 新增CORS响应头去重,保留第一个出现的有效值 .dedupeResponseHeader("Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers", "RETAIN_FIRST")) .uri("lb://auth-service")) .route("currency-exchange", r -> r.path("/currency-exchange/**") .filters(f -> f.filter(filter) .addRequestHeader(authorizationKey, authorizationValue) .dedupeResponseHeader("Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers", "RETAIN_FIRST")) .uri("lb://currency-exchange")) .route("currency-conversion", r -> r.path("/currency-conversion/**") .filters(f -> f.filter(filter) .addRequestHeader(authorizationKey, authorizationValue) .dedupeResponseHeader("Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers", "RETAIN_FIRST")) .uri("lb://currency-conversion")) .route("hindu-religious", r -> r.path("/hindu-religious/image/**") .filters(f -> f.addRequestHeader(authorizationKey, authorizationValue) .dedupeResponseHeader("Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers", "RETAIN_FIRST")) .uri("lb://hindu-religious")) .route("hindu-religious", r -> r.path("/hindu-religious/**") .filters(f -> f.filter(filter) .addRequestHeader(authorizationKey, authorizationValue) .dedupeResponseHeader("Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers", "RETAIN_FIRST")) .uri("lb://hindu-religious")) .build(); }
3. 排查重复配置
- 确认项目配置文件(application.yml/application.properties)中没有
spring.cloud.gateway.globalcors相关配置,避免和代码中的CorsWebFilter重复生效 - 再次确认下游微服务没有配置任何CORS相关过滤器、跨域适配逻辑,防止下游写入CORS头和网关配置叠加
内容的提问来源于stack exchange,提问作者AMIT
相关产品推荐
相关产品推荐

