看起来很容易添加自定义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连接

其他回答

更多的替代解决方案,但所有现代浏览器发送域cookie随着连接,所以使用:

var authToken = 'R3YKZFKBVi';

document.cookie = 'X-Authorization=' + authToken + '; path=/';

var ws = new WebSocket(
    'wss://localhost:9000/wss/'
);

以请求连接头结束:

Cookie: X-Authorization=R3YKZFKBVi

我发现最好的方法是将jwt像常规消息一样发送到服务器。让服务器监听此消息并在此时进行验证。如果有效,则将其添加到存储的连接列表中。否则,返回一条消息,说该连接无效并关闭连接。下面是客户端代码。后台是一个使用Websockets的nestjs服务器。

  socket.send(
      JSON.stringify({
        event: 'auth',
        data: jwt
      })
    );

对于那些在2021年还在苦苦挣扎的人来说,Node JS全局web套接字类在构造函数中有一个额外的选项字段。如果你去WebSockets类的实现,你会发现这个变量声明。你可以看到它接受三个参数url,这是必需的,协议(可选),这是一个字符串,字符串数组或null。第三个参数是选项。我们的兴趣,一个对象和(仍然可选)。看到……

declare var WebSocket: {
    prototype: WebSocket;
    new (
        uri: string,
        protocols?: string | string[] | null,
        options?: {
            headers: { [headerName: string]: string };
            [optionName: string]: any;
        } | null,
    ): WebSocket;
    readonly CLOSED: number;
    readonly CLOSING: number;
    readonly CONNECTING: number;
    readonly OPEN: number;
};

如果你使用的是Node Js库,比如react,请使用react-native。这里有一个例子,你可以这样做。

 const ws = new WebSocket(WEB_SOCKETS_URL, null, {
    headers: {
      ['Set-Cookie']: cookie,
    },
  });

注意,对于协议,我传递了null。如果您正在使用jwt,您可以传递带有holder +令牌的授权标头

免责声明,这可能不支持所有的浏览器外的盒子,从MDN web文档中,你可以看到只有两个参数被记录。 看到https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket语法

更新2 x

简单回答:不能,只能指定路径和协议字段。

再答:

在JavaScript WebSockets API中没有方法指定额外的头信息给客户端/浏览器发送。HTTP路径(“GET /xyz”)和协议头(“Sec-WebSocket-Protocol”)可以在WebSocket构造函数中指定。

Sec-WebSocket-Protocol报头(有时会扩展到websocket特定的认证中使用)由websocket构造函数的可选第二个参数生成:

var ws = new WebSocket("ws://example.com/path", "protocol");
var ws = new WebSocket("ws://example.com/path", ["protocol1", "protocol2"]);

上面的结果是下面的头文件:

Sec-WebSocket-Protocol: protocol

and

Sec-WebSocket-Protocol: protocol1, protocol2

A common pattern for achieving WebSocket authentication/authorization is to implement a ticketing system where the page hosting the WebSocket client requests a ticket from the server and then passes this ticket during WebSocket connection setup either in the URL/query string, in the protocol field, or required as the first message after the connection is established. The server then only allows the connection to continue if the ticket is valid (exists, has not been already used, client IP encoded in ticket matches, timestamp in ticket is recent, etc). Here is a summary of WebSocket security information: https://devcenter.heroku.com/articles/websocket-security

基本身份验证以前是一个选项,但这已经被弃用,现代浏览器即使指定了头信息也不会发送。

基本认证信息(已弃用-不再功能):

注意:以下信息在任何现代浏览器中都不再准确。

授权头是由WebSocket URI的用户名和密码(或者只是用户名)字段生成的:

var ws = new WebSocket("ws://username:password@example.com")

上面的结果是在下面的头文件中使用base64编码的字符串"username:password":

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

我已经在Chrome 55和Firefox 50中测试了基本身份验证,并验证了基本身份验证信息确实是与服务器协商的(这可能在Safari中不起作用)。

感谢德米特里·弗兰克给出的基本验证答案

所有未来调试器-直到今天,即15-07-21

浏览器也不支持向服务器发送客户标头,因此任何此类代码

    import * as sock from 'websocket'
    const headers = {
        Authorization: "bearer " + token
    };
    console.log(headers);

    const wsclient = new sock.w3cwebsocket(
        'wss://' + 'myserver.com' + '/api/ws',
        '',
        '',
        headers,
        null
    );

这在浏览器中是行不通的。这背后的原因是浏览器原生Websocket构造函数不接受头文件。

正如我上面所示,w3cwebsocket承包商接受头文件,因此很容易被误导。然而,这在node.js中是有效的。