WebSocket 鉴权问题
WebSocket API 文档:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
已知服务架构
- 前后端分离,各自使用一个域名,跨域(在后端解决了跨域问题)
- 前后端鉴权使用的是 JWT 方式
- JWT
token
通过 HTTP 请求头Authorization
字段传给后端htmlAuthorization: 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])
- 参数
url
: websocket url - 参数
protocols
可选: 协议字符串
- 参数
- 所以无法通过 JavaScript 自定义 WebSocket 标头
websocket 如何鉴权
- 在参数中传递 token,可以添加到 websocket url 中
- 通过浏览器自动发送的“隐式”身份验证(即 Basic 或 cookies)
- 此方式只能在不是跨域情况下使用,否则无法使用此方式
- 不是允许跨域就行,而是不能存在跨域
- 通过“票据”方式,流程如下:
- 客户端先通过 http 请求获取票据
- 服务端生成票据,存储后发送给客户端
- 客户端在 WebSocket 首次通信时发送此票据给服务端
- 服务端对票据进行验证
题外话,我最终使用了“隐式”身份验证;通过修改架构(类似通过配置 kong 转发)去掉了前后端跨域,最终使用 cookie 来进行鉴权的