403错误本质是WebSocket握手阶段Origin校验失败或响应头缺失,修复关键在于handshake阶段显式配置setAllowedOriginPatterns("*")(2.4+必需)、Nginx透传或清空Origin头、禁用Gateway全局CORS冲突。

403 错误本质不是“被拒绝”,而是 WebSocket 握手阶段的跨域响应头缺失或冲突 —— 修复关键在 handshake 阶段的 Origin 校验和响应头一致性,而非单纯放开 HTTP CORS。
Spring Boot 中 registerWebSocketHandlers 必须显式调用 setAllowedOrigins 或 setAllowedOriginPatterns
Spring 的 WebSocket 端点不继承全局 WebMvcConfigurer 的 CORS 配置,addCorsMappings 对 /websocket 路径完全无效。必须在 WebSocket 配置类中单独设置:
-
setAllowedOrigins("*")仅适用于 Spring Boot ≤ 2.3.x;2.4+ 版本已弃用,会抛IllegalArgumentException - 2.4+ 必须改用
setAllowedOriginPatterns("*"),否则启动报错且 403 持续存在 - 若前端带凭证(如 Cookie、JWT),需同时加
.allowCredentials(true),且 origin 不能为*,得写具体域名,例如"https://example.com" - 使用 SockJS 时,
setAllowedOriginPatterns仍需设置在addEndpoint后,不是在 SockJS 配置里
Nginx 反向代理 WebSocket 时,proxy_set_header Origin "" 是硬性要求
浏览器发起 WebSocket 升级请求时会携带原始 Origin 头,Nginx 默认透传。后端(尤其是 Spring)校验该头时,若值为 http://localhost:8080 但服务实际部署在 https://api.example.com,就会直接 403。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 必须在对应
location块中添加:proxy_set_header Origin ""(空字符串,不是"*") - 同时必须启用 WebSocket 协议升级:
proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection "$connection_upgrade" -
proxy_http_version 1.1不可省略,HTTP/1.0 不支持 upgrade 机制 - 错误写法:
proxy_pass http://backend/末尾多了一个/,会导致路径截断,使/ws变成/,后端收不到 endpoint
Spring Cloud Gateway 转发 WebSocket 时,globalcors 和应用层配置不能共存
Gateway 的全局 CORS 配置会注入 Access-Control-Allow-Origin 响应头,而 WebSocket handshake 响应只允许一个该 header。双头冲突触发浏览器拒绝握手,表现为 403 或 1002 错误码。
- 现象:Apifox 成功(不校验 CORS),浏览器失败(严格校验)
- 解决方案一(推荐):注释掉 gateway 的
globalcors配置,把跨域控制权完全交给后端 WebSocket 应用 - 解决方案二:保留 gateway CORS,但在 WebSocket 应用中移除
setAllowedOriginPatterns,并确保 gateway 的allowedOriginPatterns值与前端实际 origin 完全匹配(不能只写"*") - 注意:gateway 的
uri: lb:ws://service-name写法必须带ws://协议前缀,否则降级为 HTTP 转发,必然 403
微信小程序、Electron 或非标准浏览器环境要手动伪造 Origin 头
小程序 wx.connectSocket 发起的请求,其 Origin 值是动态生成的(如 https://servicewechat.com/xxx/devtools),后端 setAllowedOriginPatterns("*") 在部分 Spring 版本中仍会拒绝。
- 前端必须显式传
header: { Origin: "https://yourdomain.com" },且该值需与后端配置的 pattern 匹配 - 后端若用 Spring Security,还需确认
/ws/info(SockJS)或/ws(原生)路径未被 SecurityFilterChain 拦截 —— 常见遗漏点是忘了放行GET /ws/info - Electron 中
webPreferences: { webSecurity: false }可临时绕过,但上线必须靠正确配置,不能依赖关闭安全策略
最容易被忽略的是:Spring Boot 2.4+ 后,setAllowedOrigins 已彻底失效,但大量旧教程仍在用,照搬必现 403;另一个盲区是 Nginx 的 Origin 清空动作,漏掉这行,哪怕其他全对,照样握手失败。

















