看起来很容易添加自定义HTTP头到你的websocket客户端与任何HTTP头客户端支持这一点,但我不知道如何与web平台的websocket API。

有人知道怎么做到吗?

var ws = new WebSocket("ws://example.com/service");

具体来说,我需要能够发送HTTP授权标头。


当前回答

推荐的方法是通过URL查询参数

// authorization: Basic abc123
// content-type: application/json
let ws = new WebSocket(
  "ws://example.com/service?authorization=basic%20abc123&content-type=application%2Fjson"
);

这被认为是一个安全的最佳实践,因为:

WebSockets不支持头文件 在HTTP -> WebSocket升级期间,建议不要使用报头,因为CORS不是强制的 SSL加密查询参数 浏览器不会像缓存url那样缓存WebSocket连接

其他回答

在我的情况下(Azure时间序列洞察wss://)

使用ReconnectingWebsocket包装器,并能够实现添加头与一个简单的解决方案:

socket.onopen = function(e) {
    socket.send(payload);
};

本例中的有效载荷为:

{
  "headers": {
    "Authorization": "Bearer TOKEN",
    "x-ms-client-request-id": "CLIENT_ID"
}, 
"content": {
  "searchSpan": {
    "from": "UTCDATETIME",
    "to": "UTCDATETIME"
  },
"top": {
  "sort": [
    {
      "input": {"builtInProperty": "$ts"},
      "order": "Asc"
    }], 
"count": 1000
}}}

推荐的方法是通过URL查询参数

// authorization: Basic abc123
// content-type: application/json
let ws = new WebSocket(
  "ws://example.com/service?authorization=basic%20abc123&content-type=application%2Fjson"
);

这被认为是一个安全的最佳实践,因为:

WebSockets不支持头文件 在HTTP -> WebSocket升级期间,建议不要使用报头,因为CORS不是强制的 SSL加密查询参数 浏览器不会像缓存url那样缓存WebSocket连接

多亏了kanaka的回答。

客户:

var ws = new WebSocket(
    'ws://localhost:8080/connect/' + this.state.room.id, 
    store('token') || cookie('token') 
);

服务器(在本例中使用Koa2,但在其他地方应该类似):

var url = ctx.websocket.upgradeReq.url; // can use to get url/query params
var authToken = ctx.websocket.upgradeReq.headers['sec-websocket-protocol'];
// Can then decode the auth token and do any session/user stuff...

不可能发送授权头。

附加令牌查询参数是一个选项。然而,在某些情况下,以纯文本作为查询参数发送主登录令牌可能是不可取的,因为它比使用报头更不透明,并且最终会被记录在任何地方。如果这引起了您的安全问题,另一种替代方法是仅为web套接字使用第二个JWT令牌。

创建一个REST端点来生成这个JWT,当然,只有使用主登录令牌(通过报头传输)进行身份验证的用户才能访问它。web套接字JWT可以配置不同于您的登录令牌,例如有一个更短的超时,所以它是更安全的发送作为您的升级请求的查询参数。

为注册SockJS eventbusHandler的同一路由创建一个单独的JwtAuthHandler。确保先注册了认证处理程序,这样你就可以根据数据库检查web套接字令牌(JWT应该在后端以某种方式链接到你的用户)。

你不能添加头,但是,如果你只需要在连接的时候向服务器传递值,你可以在url上指定一个查询字符串部分:

var ws = new WebSocket("ws://example.com/service?key1=value1&key2=value2");

该URL是有效的,但当然,您需要修改服务器代码来解析它。