WebSocket 在不同源通信时,握手阶段需要处理 CORS 相关校验。浏览器会在建立连接前检查 Origin 头,服务端必须显式允许该来源,否则连接会被拦截。
先说结论:WebSocket 跨域通信需要在握手阶段由服务端验证 Origin 字段,并返回允许跨域的响应头。
- 适合场景:前端域名与 WebSocket 服务端域名不一致时的全双工通信。
- 优先做:在服务端配置 Access-Control-Allow-Origin 或手动校验 Origin 头。
- 再验证:通过浏览器控制台观察 WebSocket 握手状态码是否为 101。
快速处理思路
若使用 Nginx 作为反向代理,可直接在配置中添加 CORS 响应头允许特定域名访问。以下配置片段允许指定域名跨域访问 WebSocket 路径:
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
add_header 'Access-Control-Allow-Origin' 'https://example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
}若使用 Spring Boot,需实现 HandshakeInterceptor 拦截器,在 beforeHandshake 方法中校验请求头中的 Origin 字段是否在白名单内。
为什么会这样
WebSocket 连接建立前的握手过程本质是 HTTP 请求,因此受浏览器同源策略约束。虽然 WebSocket 协议基于 TCP,但初始握手阶段浏览器会携带 Origin 头标识请求来源,服务端若未明确允许该来源,浏览器会拒绝建立连接。一旦握手完成升级为 WebSocket 协议,后续数据传输不再经过 CORS 检查,因此初始握手阶段的配置至关重要。
分步处理
第一步,确认服务端框架类型。Spring Boot 应用建议实现 HandshakeInterceptor 接口,在拦截器中获取 request.getHeaders().getOrigin() 并与允许域名列表比对。Nginx 代理场景则直接修改 location 配置块。
第二步,配置允许跨域的响应头。在生产环境中禁止使用通配符*,应明确指定允许的域名,例如 Access-Control-Allow-Origin:https://client.com。若需携带 Cookie,需同时设置 Access-Control-Allow-Credentials:true。
第三步,处理 OPTIONS 预检请求。部分复杂请求可能触发 OPTIONS 预检,需在 Nginx 或服务端显式处理 OPTIONS 方法,返回 204 状态码及相应的 CORS 头。
怎么验证是否生效
打开浏览器开发者工具 Network 面板,筛选 WS 请求。观察握手请求的响应状态码,成功建立连接应返回 101 Switching Protocols。若被拦截,控制台通常显示 Access to WebSocket has been blocked by CORS policy 或 Unexpected response code:403 错误。
常见坑
生产环境禁止在 Access-Control-Allow-Origin 中使用*通配符,这会导致凭据携带失效且存在安全风险。WebSocket 连接仅在握手阶段携带 Cookie,后续通信不会自动携带,需确保握手阶段 CORS 配置允许携带凭据。部分工具如 Websocat 需通过`--custom-reply-headers` 参数手动添加跨域响应头,默认可能不包含 CORS 配置。
常见问题
WebSocket 握手失败报 403 错误怎么办?
服务端未通过 Origin 校验或 CORS 头配置缺失。检查服务端拦截器逻辑是否放行了当前请求的 Origin 域名。
配置了 CORS 头为什么还是被拦截?
可能未正确处理 OPTIONS 预检请求或 Access-Control-Allow-Credentials 未设置为 true。确认浏览器控制台具体报错信息是否涉及凭据或预检。
WebSocket 连接建立后还需要 CORS 吗?
不需要。CORS 校验仅发生在握手阶段,连接升级为 WebSocket 协议后数据传输不再受同源策略限制。
参考来源
- CSDN 博客 - WebSocket 跨域通信:构建高性能 CORS/CSRF 安全防护机制
- 彻底解决 WebSocket 跨域问题:Websocat 的 CORS 配置指南
- 前端跨域】WebSocket 如何实现跨域通信?原理、实践与安全指南
- 面试官追问的 WebSocket 跨域问题,SpringBoot 如何优雅搞定?
- Nginx 跨域问题 (CORS)