WebSocket 安全防护必须在服务端严格校验 Origin 头、握手阶段验证 JWT、强制指定子协议,三者缺一不可;禁用 ws://,确保 WSS 加密与反向代理透传关键头。

WebSocket 连接一旦暴露,就可能被任意客户端(比如 curl、Postman、恶意网页)直接连上——这不是“会不会”的问题,而是“只要没防护就一定会”。关键不是前端拦住谁,而是服务端必须拒绝非法连接。
Origin 头校验必须做,且不能只靠 Referer
浏览器在发起 WebSocket 握手时会带 Origin 请求头,这是唯一可依赖的跨域标识。服务端不校验它,等于把门敞开给钓鱼页面。
- 只接受明确白名单域名,例如
https://app.example.com、https://admin.example.com,拒绝http://或空值(开发环境除外) - 绝对不要用通配符
*或正则模糊匹配(如/^https:\/\/.*\.example\.com$/),攻击者可伪造 Origin 字符串绕过 -
Referer不可靠:可被客户端篡改,且某些请求(如从书签打开)根本不会带它
JWT 必须在握手阶段验证,不能拖到连接建立后
把 token 放在 URL 参数里(如 ws://api/?token=xxx)是高危操作——日志、代理、CDN 都可能记录它。真正安全的做法是在握手请求中携带凭证,并立刻验证。
- 推荐方式:前端用
Cookie(HttpOnly+Secure+SameSite=Strict),服务端读取 session 并绑定 WebSocket 实例 - 次选方式:前端在
Sec-WebSocket-Protocol头里传 token(如['myapp-v1', 'Bearer eyJhb...']),服务端提取并验证 JWT - 严禁方式:连接建立后再等客户端发第一条
{"type":"auth"}消息——此时连接已占资源,攻击者可维持大量半认证连接耗尽服务器
子协议(subprotocol)不是可选项,是识别层过滤器
Sec-WebSocket-Protocol 本身不防攻击,但它能快速筛掉非正规客户端。curl、Python websocket-client 默认不设该头,恶意脚本也常忽略。
- 前端创建时必须指定:
new WebSocket('wss://api.example.com/ws', ['myapp-v2']) - 服务端拒绝任何未声明或不在白名单里的协议名,例如
req.headers['sec-websocket-protocol'] !== 'myapp-v2'就调用socket.destroy() - 配合 Origin 和 JWT,三者缺一不可:Origin 防跨站、JWT 防冒充、subprotocol 防脚本暴力探测
WSS 加密和反向代理配置直接影响鉴权有效性
如果用 ws:// 明文传输,哪怕 Origin 和 JWT 都校验了,中间人也能劫持并重放合法请求。而反向代理若未透传 Origin 或 Cookie,服务端看到的永远是代理 IP 和空头信息。
- 强制使用
wss://,禁用ws://端点(Nginx 可用return 403拦截) - Nginx 配置中必须显式透传关键头:
proxy_set_header Origin $http_origin;、proxy_pass_request_headers on; - 若用 Cloudflare 等 CDN,确认其未剥离
Origin头(部分免费版默认剥离)
最易被忽略的一点:Origin 校验和 JWT 验证必须在同一个代码路径里完成,且在 upgrade 事件回调的最开头执行。任何延迟(比如先打印日志、再查数据库)都可能被并发请求打穿防线。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











