websocket连接返回403通常源于握手阶段被拦截,需逐层排查nginx、spring security、spring boot配置及网关代理问题,而非简单设置allowedorigins。

WebSocket连接返回403,基本不是权限问题,而是握手阶段被拦截——要么服务端没放行Upgrade请求,要么代理层丢掉了关键Header,要么Spring Security在中间卡住了。直接改allowedOrigins="*"往往无效,得看具体在哪一层出的问题。
Spring Boot + WebSocket 端点被403拦截
常见于用@EnableWebSocket或WebSocketHandlerRegistry注册端点后,前端连不上,浏览器Network里看到GET请求返回403。
-
addEndpoint("/ws")必须显式调用setAllowedOrigins("*")(新版用setAllowedOriginPatterns("*")),仅配CORS全局过滤器不管用 - 如果用了
SockJS,注意/ws/info这个初始探测请求也得放行,它走的是HTTP,不是WS协议 - Spring Boot 2.6+默认禁用
/**通配,setAllowedOrigins("*")会报错,必须换setAllowedOriginPatterns("*") - 若项目启用了Spring Security,
/ws/**路径必须在WebSecurity.ignoring()里声明,否则SecurityFilterChain会提前拦截Upgrade请求
Nginx反向代理下WebSocket握手失败
本地直连OK,部署到Nginx后出现Error during WebSocket handshake: Unexpected response code: 403,大概率是Nginx没透传协议升级头。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 必须在
location块里显式设置proxy_http_version 1.1,HTTP/1.0不支持Upgrade -
proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection "$connection_upgrade"缺一不可;$connection_upgrade需在http块提前定义:map $http_upgrade $connection_upgrade { default upgrade; '' close; } - 不要设
proxy_set_header Origin ""——这会清空Origin头,导致后端跨域校验失败;如需绕过校验,应在后端处理,而非在Nginx伪造 - 确认Nginx监听端口没被防火墙或SELinux拦截,尤其CentOS系常因SELinux阻止非标准端口的WebSocket流量
Spring Cloud Gateway转发WebSocket时403
网关配置了全局CORS,但ws://请求仍403,因为Gateway的CORS Filter默认不处理WebSocket协议升级请求。
- Gateway的
globalcors只对HTTP请求生效,对ws://或wss://协议无效;必须用lb:ws://或lb:wss://作为uri,并确保predicates匹配到Upgrade请求路径 - 避免在Gateway和后端服务同时配置CORS,重复设置
Access-Control-Allow-Origin会导致浏览器拒绝响应(报“header contains multiple values”) - 若后端是Spring WebFlux,记得在路由filter中加
StripPrefix=1,否则路径错位可能让端点匹配失败,间接触发403 - 测试时优先用
wscat -c "ws://..."绕过浏览器CORS限制,快速定位是协议层还是浏览器层问题
真正容易被忽略的点:403错误日志里几乎不打印具体拦截位置,得靠抓包看哪个环节返回了403——是Nginx?是Gateway?是Spring Security Filter?还是后端WebSocket Handler自己抛的?每层的修复方式完全不同,别在allowedOrigins上死磕。










