websocket url传参必须用标准查询字符串格式,即?k1=v1&k2=v2,不可省略?,也不能用#或路径拼接;中文及特殊字符需前端encodeuricomponent()编码,后端通过session.getquerystring()获取并解析。

WebSocket URL 里怎么传 query 参数
必须用标准查询字符串格式,?key=value&key2=value2,不能省略 ?,也不能塞进 # 或路径里。浏览器原生 WebSocket 构造函数只认这个位置的参数。
- ✅ 正确:
new WebSocket("wss://api.example.com/chat?token=abc123&room=general") - ❌ 错误:
new WebSocket("wss://api.example.com/chat#token=abc123")——#是 fragment,服务端根本收不到 - ❌ 错误:
new WebSocket("wss://api.example.com/chat/token=abc123")—— 这会被解析成路径/chat/token=abc123,不是 query - 中文或特殊字符(空格、
/、+)必须前端用encodeURIComponent()编码,否则后端收到乱码 - Spring Boot 中用
@ServerEndpoint时,session.getQueryString()返回原始字符串(如"token=abc123&room=general"),需手动拆分或用org.springframework.util.StringUtils.parseQuery()解析
WebSocket 能不能在 Header 里传 token
标准浏览器 WebSocket API 不允许直接设置自定义请求头,但握手阶段本质是 HTTP 请求,部分环境(如 Node.js 客户端、测试工具、或配合反向代理)可以注入 Authorization 或其他头;更通用且兼容的做法是复用 Sec-WebSocket-Protocol 字段。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
Sec-WebSocket-Protocol原本用于协商子协议(如["chat", "binary"]),但可“借位”传 token:new WebSocket(url, ["Bearer abc123"]) - 后端必须原样返回该值到响应头
Sec-WebSocket-Protocol: Bearer abc123,否则连接会失败 - 服务端获取方式:
request.getHeader("Sec-WebSocket-Protocol")(Java Servlet)或等价 API - 如果用 Nginx 反向代理,可在配置中添加:
proxy_set_header Authorization $http_authorization;,再配合客户端构造带Authorization头的请求(需非浏览器环境或定制 client) - 浏览器环境无法直接发
Authorization头,强行尝试会报InvalidAccessError
WebSocket 路径参数怎么用(/chat/{id} 类型)
路径参数和 query 参数是两套机制:路径参数靠服务端路由匹配提取,不参与 URL 编码规则,也不出现在 query string 中;适合标识资源实例(如用户 ID、房间号)。
- 前端 URL 示例:
ws://localhost:8080/chat/123,其中123是路径段,不是 query - Spring Boot +
@ServerEndpoint("/chat/{userId}")时,可用@PathParam("userId") String userId直接注入 - 也可通过
session.getPathParameters()拿到 Map:{"userId": "123"} - 注意:路径参数无法动态拼接进
new WebSocket(url)后再修改——URL 是一次性构造的,改路径就得换整个 URL 字符串 - 路径参数不经过编码/解码环节,所以不要放含
/、?的值,否则路由匹配失败
为什么 query 和 header 传参容易混淆出错
根本原因在于 WebSocket 握手是 HTTP 升级过程,但浏览器 API 把它封装成一个“连接动作”,掩盖了底层请求细节。开发者常误以为能像 fetch() 那样自由设 header,或把路径当 query 用。
- query 参数看似简单,但没
encodeURIComponent()就崩——比如 token 里有+,后端 decode 出来变空格 -
Sec-WebSocket-Protocol传 token 是权宜之计,但它不是设计用途,语义不清,多人协作时容易被当成真子协议处理 - 路径参数看着直观,但一旦写成
/chat?id=123就变成 query,和/chat/123完全是两个路由逻辑,后端可能 404 - 真正需要 header 级认证(如 JWT)又受限于浏览器,这时候得考虑是否该用长轮询过渡,或接受连接后立刻 send 认证消息(不安全,仅限内网调试)










