浏览器websocket不支持设置自定义请求头(如authorization),因规范限制仅允许upgrade、connection等特定头部;可行方案包括url传token、cookie自动携带或连接后发送鉴权帧。

WebSocket 协议本身不支持在握手阶段直接携带自定义请求头(如 Authorization、X-User-ID 等),因为浏览器端的 WebSocket 构造函数(new WebSocket(url, protocols))**不允许设置自定义 HTTP 请求头**。这是浏览器安全策略限制,不是 HTML5 或 WebSocket 协议本身的缺陷,而是出于防止跨站请求伪造(CSRF)等风险的设计约束。
为什么不能直接加自定义协议头?
根据 WHATWG 规范和主流浏览器实现,WebSocket 连接初始化时发起的 HTTP Upgrade 请求,其请求头是严格受限的。仅允许以下字段由浏览器自动设置或通过 protocols 参数间接影响:
Upgrade: websocketConnection: Upgrade-
Sec-WebSocket-Key、Sec-WebSocket-Version、Sec-WebSocket-Protocol -
Origin(由浏览器自动添加,不可覆盖)
像 Authorization、Cookie(若未开启 withCredentials)、X-* 类自定义头均被明确禁止传入。
可行的身份鉴权替代方案
虽然不能发自定义头,但可通过以下方式安全、可靠地完成用户身份验证与鉴权:
-
URL 查询参数传递临时凭证:将短期有效的 token(如 JWT)拼在 WebSocket URL 后,例如:
ws://example.com/ws?token=eyJhbGciOiJIUzI1Ni...&uid=123
服务端在upgrade阶段解析 URL,校验 token 有效性、签名、过期时间及绑定信息(如 uid、IP、user-agent 指纹)。注意:避免在 URL 中暴露敏感长期凭证(如密码、密钥),且需防范日志泄露(Nginx/Apache 默认记录完整 URL)。 -
基于 Cookie 的自动携带(推荐):若 WebSocket 服务与主站同域(或配置了合适的 CORS + Cookie 策略),可提前通过 HTTP 接口设置
HttpOnly=false、Secure、SameSite=Lax(或None)的认证 Cookie。浏览器会在 WebSocket Upgrade 请求中自动带上该 Cookie。服务端从cookie字段解析并校验 session 或 token。此方式无需前端显式传参,更符合 Web 安全惯例。 -
握手后立即发送鉴权帧:建立连接后,客户端立刻发送一条 JSON 或二进制格式的认证消息(如
{"type":"auth","token":"..."}),服务端收到后验证,成功则标记连接为已认证,失败则关闭连接。需配合连接状态管理(如 Redis 存储 pending 连接 ID),防止未鉴权连接占用资源。
服务端实现要点(以 Node.js + ws 库为例)
在升级前拦截请求,提取凭证并校验:
const WebSocket = require('ws');
const http = require('http');
const server = http.createServer();
const wss = new WebSocket.Server({ noServer: true });
server.on('upgrade', async (req, socket, head) => {
// 1. 解析 URL 查询参数
const url = new URL(req.url, 'http://localhost');
const token = url.searchParams.get('token');
// 2. 或从 Cookie 解析(需手动解析 req.headers.cookie)
const cookies = parseCookies(req.headers.cookie);
const sessionId = cookies['session_id'];
try {
// 3. 异步校验(JWT 验证 / Session 查询 / DB 查用户)
const user = await verifyTokenOrSession(token || sessionId);
if (!user) throw new Error('Invalid auth');
// 4. 允许升级,附带用户上下文
wss.handleUpgrade(req, socket, head, (ws) => {
ws.user = user; // 挂载到 ws 实例
wss.emit('connection', ws, req);
});
} catch (err) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
}
});
安全注意事项
无论采用哪种方式,都必须遵守以下原则:
- 所有 token 必须有明确过期时间(如 5 分钟),且服务端强制校验
exp字段; - 避免在 URL 中传递长期有效的密钥或密码;
- WebSocket 连接建立后,仍需对后续每条敏感消息做权限检查(如频道订阅、指令执行),不能仅依赖初始鉴权;
- 使用 WSS(WebSocket Secure)而非 WS,确保传输层加密,防止 token 被中间人截获;
- 限制单个 IP 或用户并发连接数,防范暴力重连或 token 扫描攻击。
不复杂但容易忽略:鉴权不是“连上即可信”,而应贯穿连接生命周期——从握手、首帧、到每条业务消息。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











