WebSocket跨域需在HTTP Upgrade握手阶段校验Origin并完成鉴权,不可延至连接建立后;推荐URL传短期Token,Cookie方式须前后端协同配置Access-Control-Allow-Origin具体域名及withCredentials:true。

WebSocket 本身不走 CORS 检查,但跨域连接仍受浏览器同源策略影响——关键在握手阶段的 HTTP Upgrade 请求是否被服务端允许。鉴权必须嵌入这个阶段,不能等连接建立后再验证。
WebSocket 跨域不是“绕过”CORS,而是受限于 Origin 校验
浏览器发起 WebSocket 连接时,会先发一个带 Origin 头的 HTTP Upgrade 请求。它不像普通 AJAX 那样触发预检(preflight),但服务端必须显式校验该 Origin 是否合法,否则连接会被拒绝(如返回 403 或直接断连)。
- 服务端必须读取
req.headers.origin(Node.js)或request.getHeaders().getOrigin()(Spring),并比对白名单 - 若需携带 Cookie,服务端响应 101 状态时必须包含:
Access-Control-Allow-Origin: https://your-frontend.com(不能是*)Access-Control-Allow-Credentials: true - 前端创建连接时,必须加
withCredentials: true,否则浏览器根本不会发送 Cookie
Token 鉴权必须在握手时完成,不能靠 onopen 后发消息
连接一旦升级为 WebSocket 协议,服务端就无法中断或拒绝——此时未授权连接已占用资源,且攻击者可跳过 auth 消息直发业务帧。
- 推荐方式:URL 参数传短期 Token,例如
new WebSocket("wss://api.example.com/ws?token=" + encodeURIComponent(wsToken)) - 替代方式:借用
Sec-WebSocket-Protocol字段,前端写new WebSocket(url, ["Bearer xxx"]),服务端从请求头中提取 - 更安全方式:Nginx 反向代理注入 Authorization 头,后端统一按标准 Header 解析
Cookie 方式需前后端协同配置,稍有疏漏即失败
即使前后端同主域但端口不同(如 http://localhost:3000 → wss://localhost:8080),浏览器默认也不发 Cookie,必须显式开启凭据传递。
立即学习“Java免费学习笔记(深入)”;
- 前端:只能用
withCredentials: true,credentials: 'include'无效 - 后端:响应头中
Access-Control-Allow-Origin必须是具体域名,不可为*;同时返回Access-Control-Allow-Credentials: true - 服务端代码中要主动读取 Cookie,例如 Go 中用
r.Cookies(),Java 中用request.getCookies(),并校验 session_id 等字段
避免常见错误配置
很多跨域连接失败,不是因为技术不可行,而是配置冲突或逻辑错位。
- Spring Boot 项目中,WebSocket 路径不能被 Spring Security 设为
permitAll(),必须通过HandshakeInterceptor在beforeHandshake中校验 - Nginx 代理时,要透传
Origin头:proxy_pass_request_headers on;,并手动添加 Access-Control 响应头 - Token 不能复用登录态 JWT,必须调用专用接口(如
/api/v1/ws-token)获取短期凭证,且服务端需校验 Redis 黑名单


















