Skip to content

WebSocket 鉴权问题

WebSocket API 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

已知服务架构

  • 前后端分离,各自使用一个域名,跨域(在后端解决了跨域问题)
  • 前后端鉴权使用的是 JWT 方式
  • JWT token 通过 HTTP 请求头 Authorization 字段传给后端
    html
    Authorization: Bearer <token>
  • JWT token 同时存于 cookie 中,但在跨域情况下 cookie 并不会自动发送(可通过配置 Access-Control-Allow-Credentials 响应头来解决)

最重要的问题

WebSocket 无法添加 header !!!

  • 网上的一些添加 header 的文档资料、代码片段均存在错误(也许是旧版可用、也可能是用的其它 WebSocket 客户端)
  • 但在这里咱们提到的 WebSocket 均为 javascript 自带的 WebSocket 客户端
  • 通过 WebSocket 的构造函数可以看出,其只有两个参数:
    js
    const ws = new WebSocket(url [, protocols])
    1. 参数 url: websocket url
    2. 参数 protocols可选: 协议字符串
  • 所以无法通过 JavaScript 自定义 WebSocket 标头

websocket 如何鉴权

  • 在参数中传递 token,可以添加到 websocket url 中
  • 通过浏览器自动发送的“隐式”身份验证(即 Basic 或 cookies)
    • 此方式只能在不是跨域情况下使用,否则无法使用此方式
    • 不是允许跨域就行,而是不能存在跨域
  • 通过“票据”方式,流程如下:
    1. 客户端先通过 http 请求获取票据
    2. 服务端生成票据,存储后发送给客户端
    3. 客户端在 WebSocket 首次通信时发送此票据给服务端
    4. 服务端对票据进行验证

题外话,我最终使用了“隐式”身份验证;通过修改架构(类似通过配置 kong 转发)去掉了前后端跨域,最终使用 cookie 来进行鉴权的

参考