WebSocket认证Token必须在握手阶段通过WSS加密通道安全传递,推荐使用子协议字段(Sec-WebSocket-Protocol头),次选连接后立即发送认证帧,禁用URL参数方式;Token需设exp/jti、绑定设备指纹,并优先存于httpOnly Cookie。

WebSocket 本身不支持在连接建立后动态设置认证头,所以 Token 必须在握手阶段或刚连通时安全送达。关键不是“能不能传”,而是“怎么传才不暴露、不被劫持、不被重放”。核心前提是:所有方案都必须运行在 WSS(即 TLS 加密) 环境下,否则任何 Token 都是明文裸奔。
用子协议字段传递 Token(推荐)
这是目前最平衡安全与兼容性的方案。浏览器 WebSocket 构造函数允许传入一个子协议数组(protocols),它会作为 Sec-WebSocket-Protocol 头出现在握手请求中,且不会被记录到 URL 或浏览器历史里。
- 前端写法示例:
const socket = new WebSocket('wss://api.example.com/ws', ['Bearer ' + token]); - 服务端可直接从握手请求的
Sec-WebSocket-Protocol头提取并验证,无需解析 URL 或等待首帧 - 注意子协议值不能含非法字符,建议统一前缀(如
auth-jwt或Bearer),避免与其他子协议冲突 - 部分老版本 Safari 对子协议长度有限制(建议控制在 128 字符内),JWT 可精简 payload 字段或使用短签名算法
连接建立后立即发送认证帧(稳妥但需配合心跳)
先建立连接,再立刻发一条 JSON 消息携带 Token。这种方式完全避开握手限制,也规避了 URL 和子协议的潜在风险。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 客户端在
onopen回调中第一时间发送:socket.send(JSON.stringify({ type: 'auth', token: localStorage.getItem('auth_token') })); - 服务端收到后验证,若失败则立即关闭连接(返回 4001 错误码),并拒绝后续所有消息
- 必须搭配超时机制:如果 3 秒内未收到有效 auth 帧,服务端主动断连,防止“空连接”堆积
- 前端需监听
onerror和onclose,对 4001 码做明确处理(如跳转登录页)
URL 参数方式(仅限低风险场景)
虽然简单,但存在明显泄露面,只适合内部系统、临时调试或配合极短时效 Token(如 5 分钟)使用。
- 务必对 Token 做
encodeURIComponent编码,避免特殊字符截断 - 服务端验证通过后,应立即将该 Token 标记为“已使用一次”,防止重放
- Nginx/Apache 日志中需过滤掉
token=类参数,或禁用相关日志记录 - 绝对不可用于生产环境的用户主业务通道(如聊天、交易)
Token 本身的安全强化要点
无论用哪种传输方式,Token 设计不当会让所有努力白费。
- 使用 JWT 时,必须设置
exp(过期时间)和jti(唯一编号),服务端做防重放校验 - 签发时绑定设备指纹或 session ID,增加伪造成本
- 前端存储不用
localStorage,优先用httpOnlyCookie(配合 SameSite=Strict),或内存变量 + 登录态兜底 - Token 过期前 60 秒,前端主动触发刷新逻辑,避免连接中断后重连失败

















