浏览器中 websocket 鉴权只能将 token 拼在 url 查询参数中并 encodeuricomponent 编码,服务端通过 verifyclient 钩子解析校验;不可用 headers,因浏览器不支持设置自定义请求头。

WebSocket 连接不能在建立后补发鉴权头,所以必须在 new WebSocket() 的 URL 中携带 Token,或通过 Sec-WebSocket-Protocol / 自定义 header(仅服务端可控时)传递——但浏览器环境不支持设置任意请求头。
浏览器里怎么传 Token:只能拼在 URL 上
HTTP 协议允许在 WebSocket 握手请求(Upgrade 请求)中携带查询参数,这是浏览器唯一可靠的方式。服务端从 url.query 或 req.url 解析即可。
- 不要试图用
headers选项(WebSocket构造函数不接受该参数) - 避免把敏感 Token 放在 URL 中被代理、CDN、日志误记录;如需更高安全性,应改用短期有效的临时 Token
- URL 编码必须做:
encodeURIComponent(token),否则含+、/、=的 JWT 会解析失败
示例:
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
const ws = new WebSocket(`wss://api.example.com/ws?token=${encodeURIComponent(token)}`);
Node.js 后端(ws 库)如何校验 URL 中的 Token
使用 ws 库时,verifyClient 钩子可拦截握手请求并拒绝非法连接,比在 connection 事件里校验更早、更安全。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
info.req.url是完整路径+查询字符串,需手动解析(推荐用url.parse()或new URL()) - 校验失败必须同步返回
{ reject: true },异步校验(如查数据库)需自行缓存或改用upgrade事件 + 手动socket.destroy() - 注意:若用 Express +
ws共享 server,确保verifyClient在http.Server实例上注册,而非ws.Server初始化时传入
简例(同步校验):
const { URL } = require('url');
const wss = new WebSocket.Server({
server,
verifyClient: (info) => {
const url = new URL(info.req.url, 'http://x');
const token = url.searchParams.get('token');
if (!token || !verifyJWT(token)) return { reject: true };
return { reject: false };
}
});
为什么不能用 fetch + Headers 模拟 WebSocket 握手
WebSocket 握手是 HTTP Upgrade 协议交互,不是普通 HTTP 请求。fetch 不支持 Upgrade: websocket,也无法复用底层 TCP 连接——它根本不会触发 WebSocket 协议升级流程。
- 试图用
fetch发起带Authorization头的请求,得到的只是 200 响应体,和真正的 WebSocket 连接无关 - 某些调试工具(如 curl)能发 Upgrade 请求,但仅用于测试;浏览器 JS API 完全不开放该能力
- 如果服务端强制要求 Header 鉴权(如
Authorization: Bearer xxx),那它必须运行在非浏览器环境(如 Node.js 客户端、App 内 WebView 配合原生桥、或 Electron)
真实项目里容易漏掉的点
Token 过期时间通常短于 WebSocket 生命周期,但连接一旦建立就不会自动重鉴权。客户端需监听 onclose,检查 event.code 是否为 4001(自定义鉴权失败码),再用新 Token 重连。
- 别依赖
onerror:鉴权失败时,服务端一般直接断连,触发的是onclose而非onerror - 服务端主动踢人时,应发
close(4001, 'auth expired')而非静默断连,方便前端区分原因 - 多个 tab 同时连接?Token 复用可能引发并发鉴权冲突,服务端需支持“单设备登录”或连接绑定 session










