Spring Cloud Gateway+WebSocket服务+Angular架构下CORS跨域头重复错误求助
从你给出的错误信息和配置来看,问题的核心非常明确:Spring Cloud Gateway和后端WebSocket服务同时在响应中添加了Access-Control-Allow-Origin头,导致浏览器检测到重复值,触发了同源策略拦截。绕过网关直接连接后端正常,也验证了这一点——后端单独的CORS配置是没问题的,冲突来自网关的全局CORS配置和后端配置的叠加。
下面给你两种可行的解决方案,你可以根据自己的架构偏好选择:
方案一:移除后端WebSocket的CORS配置,让网关统一处理跨域
既然已经在网关层做了全局CORS控制,后端服务(包括WebSocket端点)就不需要再单独配置跨域了——因为后端和网关属于内部调用,不存在跨域问题,跨域只需要在网关和前端之间处理。
修改你的后端WebSocketConfig类,移除setAllowedOriginPatterns("*")这一行:
@Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry .addEndpoint("/ws") // 移除跨域配置,交由网关统一处理 .withSockJS(); }
方案二:调整网关CORS配置,排除WebSocket相关路径
如果你不想修改后端配置,可以让网关不对WebSocket的请求路径应用CORS过滤,把跨域处理完全交给后端。
修改网关的corsFilter()方法,优先给WebSocket相关路径注册一个空的CORS配置(即不添加任何CORS头),再注册全局配置:
private CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); // 你的原有配置保持不变 config.setAllowCredentials(true); config.setAllowedOriginPatterns(Collections.singletonList("*")); config.addAllowedHeader(ORIGIN); config.addAllowedHeader(CONTENT_TYPE); config.addAllowedHeader(ACCEPT); config.addAllowedHeader(AUTHORIZATION); config.addAllowedHeader(CONNECTION); config.addAllowedHeader(ACCEPT_ENCODING); config.addAllowedHeader(USER_AGENT); config.addAllowedHeader(CONTENT_LENGTH); config.addAllowedHeader(HOST); config.addAllowedHeader("Postman-Token"); config.addAllowedHeader(COOKIE); config.addAllowedMethod(GET); config.addAllowedMethod(PUT); config.addAllowedMethod(POST); config.addAllowedMethod(OPTIONS); config.addAllowedMethod(DELETE); config.addAllowedMethod(PATCH); config.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); // 优先匹配WebSocket路径,应用空配置(网关不添加CORS头) source.registerCorsConfiguration("/**/ws/**", new CorsConfiguration()); // 再注册全局CORS配置 source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); }
注意:UrlBasedCorsConfigurationSource会按照路径的具体程度优先匹配,所以一定要把WebSocket的路径配置放在全局配置前面。
额外说明
SockJS在建立WebSocket连接前,会先发送一个OPTIONS请求到/ws/info接口获取连接元信息,这个请求是触发CORS检查的关键。无论你选哪种方案,最终要确保这个请求的响应中只有一个Access-Control-Allow-Origin头。
修改完成后,重启网关和后端服务,再用Angular应用测试连接,应该就能解决这个CORS错误了。
内容的提问来源于stack exchange,提问作者Alexander Mladzhov

