Spring Cloud Gateway + WebSocket + SockJS 踩坑记录:响应头重复全解析!
哪怕你网关 CORS 配好了,只要 WebSocket 后端服务没有 `.setAllowedOriginPatterns()`,Spring WebSocket 默认会 **拒绝跨域握手请求(403)**通过网关走websocket服务,因为此时gateway配置文件中已经配置了跨域。WebSocket 连接顺利建立,跨域问题解决。浏览器收到的响应头不再重复,跨域请求正常通过。Gateway 的
冲突前提: 客户端使用 SockJS + STOMP 接入,后端通过 Spring WebSocket + RabbitMQ(开启了 STOMP 协议插件)进行消息转发。由于 Gateway 和 RabbitMQ 都可能在响应中添加 Access-Control-Allow-Origin,导致响应头重复,WebSocket 握手失败。
通过网关走websocket服务,因为此时gateway配置文件中已经配置了跨域

但是websocket也需要配置跨域,原因:
重点解释:为什么光网关配置跨域还不够
WebSocket 的握手预检请求(OPTIONS)流程如下:
-
浏览器 → Gateway:OPTIONS 请求 Gateway 的 CORS 配置放行,然后把请求转发给 WebSocket 服务
-
Gateway → WebSocket 服务:OPTIONS 转发过去了 这时候由后端
Spring WebSocket服务来处理 -
但你后端没有
.setAllowedOriginPatterns("\*"),于是直接 403
哪怕你网关 CORS 配好了,只要 WebSocket 后端服务没有 .setAllowedOriginPatterns(),Spring WebSocket 默认会 拒绝跨域握手请求(403)
所以需要在gateway配置文件中websocket模块的配置中添加:
- DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_FIRST
- DedupeResponseHeader=Access-Control-Allow-Credentials, RETAIN_FIRST
-
Gateway 会检查响应头中的
Access-Control-Allow-Origin和Access-Control-Allow-Credentials字段,只保留第一个,去掉重复的。 -
浏览器收到的响应头不再重复,跨域请求正常通过。
-
WebSocket 连接顺利建立,跨域问题解决。
最终效果:

总结
- 在多层跨域配置的场景下(网关 + 后端),应避免多处重复添加跨域头。
- 利用 Gateway 的 `DedupeResponseHeader` 过滤器是简洁有效的解决方案。
- 后续跨域配置推荐统一在网关层处理,后端只做必要的允许配置,避免响应头重复。
注:本文记录的是我在使用 Spring Gateway + SockJS + RabbitMQ 的过程中遇到的问题,可能不是所有场景都适用,但希望对你排查类似问题有所启发。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)