websocket 客户端需将 jwt token 通过 `authorization: bearer
在基于 WebSocket 的实时通信场景中,安全地完成用户身份鉴权至关重要。许多开发者误以为可通过 URL 查询参数(如 ?token=xxx 或 ?access_token=xxx)向 WebSocket 服务端传递 JWT,但实际中——尤其是使用 dgrijalva/jwt-go(现维护分支为 golang-jwt/jwt)等标准库进行解析时——服务端验证逻辑默认不解析查询参数中的 token。
如问题中 Go 服务端代码所示,ParseFromRequest 函数仅检查两个位置:
而 WebSocket 握手请求(HTTP Upgrade)不会自动将 URL 查询参数注入 req.Form,即使调用了 req.ParseMultipartForm(10e6),该方法也仅处理 multipart/form-data 类型的请求体(常见于文件上传),对 application/x-www-form-urlencoded 或纯 query string 无作用。因此 req.Form.Get("access_token") 始终为空,最终返回 ErrNoTokenInRequest。
✅ 正确做法:将 Token 放入 Authorization 请求头
使用 Python 客户端(如 websocket-client)时,应通过 header 参数显式传入认证头:
from websocket import create_connection
def test_auth_token(token):
# ✅ 正确:通过 Header 传递 Bearer Token
headers = ["Authorization: Bearer " + token]
ws_url = f"ws://:port/{container.uuid}"
conn = create_connection(ws_url, header=headers)
result = conn.recv()
assert result is not None
conn.close() ⚠️ 注意事项:
? 扩展建议:
服务端可增强兼容性,例如主动从 req.URL.Query().Get("access_token") 读取查询参数(需自行实现,非 jwt-go 默认行为)。但推荐客户端统一走 Header 方案,既符合 OAuth 2.0 / RFC 6750 规范,也便于与现有 HTTP API 鉴权逻辑保持一致。