websocket 客户端需将 jwt token 通过 `authorization: bearer
在 WebSocket 协议中,连接建立阶段本质上是 HTTP Upgrade 请求(即 GET 请求携带 Upgrade: websocket 头),因此客户端可且应当像普通 HTTP 请求一样,在请求头中携带认证信息。而你当前的实现——将 token 拼入 URL 查询参数(如 ?token=xxx 或 ?access_token=xxx)——虽语法合法,但无法被 jwt-go 的 ParseFromRequest 函数识别,原因如下:
ParseFromRequest 的源码逻辑明确只检查两个位置:
⚠️ 关键点:WebSocket 握手请求是纯 HTTP GET,不包含请求体,也不触发自动表单解析。即使你在 URL 中添加 ?access_token=xxx,req.Form 默认为空(除非显式调用 req.ParseForm()),且 ParseFromRequest 并未尝试从 req.URL.Query() 中提取参数。
使用支持自定义 header 的 WebSocket 客户端库(如 websocket-client),在握手请求中注入 Authorization 头:
from websocket import create_connection
def test_auth_token(token, ip, port, uuid):
url = f"ws://{ip}:{port}/{uuid}"
headers = [f"Authorization: Bearer {token}"] # ✅ 关键:Bearer + 空格 + token
conn = create_connection(url, header=headers)
try:
result = conn.recv()
print("Connected and received:", result)
assert result is not None
finally:
conn.close()? 注意:header 参数接受字符串列表,每项为 "Key: Value" 格式;Authorization 头值必须严格为 Bearer (注意大小写与空格)。
确保你的 Go WebSocket 服务在 Upgrade 前对原始 HTTP 请求进行 token 验证。例如(使用 gorilla/websocket):
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// 在 Upgrade 前验证 token
token, err := jwt.ParseFromRequest(r, func(token *jwt.Token) (interface{}, error) {
return []byte("your-secret-key"), nil // 实际应使用公钥或安全密钥管理
})
if err != nil || !token.Valid {
return false
}
// 可选:将用户信息存入 context 或 session
return true
},
}若需更灵活的 token 提取(如支持查询参数),可自行封装解析逻辑,但不推荐——因查询参数易被日志、代理、CDN 缓存泄露,存在安全风险;Header 是标准、安全且符合 JWT 最佳实践的方式。