使用中间件和 node.js 表达的 Websockets 令牌认证

cod*_*bot 1 authentication token websocket node.js express

我使用基于ws 的node.js、express 和express- ws

Express-ws 允许为 websockets 创建类似 express 的端点。

我正在寻找一种基于令牌在 websocket 连接中对用户进行身份验证的解决方案。由于我的 ws 服务器是基于 HTTP 的

const wsHttpServer = http.createServer();
wsHttpServer.listen(5001);
const expressWs = require('express-ws')(app , wsHttpServer);
Run Code Online (Sandbox Code Playgroud)

并且由于 ws 连接基于升级为 ws 的 HTTP 连接,为什么我不能像其他任何连接一样在快速路由检查的 ws 中传递令牌?我的逻辑是,发送令牌,检查它,如果没问题,继续升级到 ws 连接。因此,我可以重用 HTTP 连接中的令牌中间件解决方案。

在节点

我的 ws 服务器

const wsHttpServer = http.createServer();
wsHttpServer.listen(5001);
const expressWs = require('express-ws')(app , wsHttpServer);

//set the route

app.use('/ws', require('./routes/wsroute')); 
Run Code Online (Sandbox Code Playgroud)

在该路线中,我想使用token.validate()中间件 - 在 HTTP 连接中,检查 Authorization 标头

router.ws('/user/:name/:id', token.validate(),  (ws, req) => { 
    console.log('ws route data : ',vessel, req.params.name, req.params.id);
});
Run Code Online (Sandbox Code Playgroud)

在我的客户端

    const socket = new WebSocket('ws://localhost',{
        path: '/user/Nick/25/',
        port: 5001, // default is 80
        protocol : "echo-protocol", // websocket protocol name (default is none)
        protocolVersion: 13, // websocket protocol version, default is 13
        keepAlive: 60,
        headers:{ some:'header', 'ultimate-question':42 } // websocket headers to be used e.g. for auth (default is none)
      });
Run Code Online (Sandbox Code Playgroud)

这个错误 Failed to construct 'WebSocket': The subprotocol '[object Object]' is invalid

我也试过

const socket = new WebSocket('ws://localhost:5001/user/Nick/25', ["Authorization", localStorage.getItem('quad_token')]);

我没有收到任何错误,但我不知道如何Authorization在节点中获取“标题”

我可以

只需发送const socket = new WebSocket(currentUrl);一些数据并在该数据中包含一个有效的令牌。但是要检查它,我必须先允许连接。我不想要那个,我想使用一个中间件解决方案来自动检查令牌并允许或不继续。

问题

请帮我理解:

1 是否可以在 ws 中使用基于令牌、基于中间件的解决方案?

2 如何在 ws 连接中设置带有令牌的标头?

3 如何在节点中获取该令牌?

小智 7

1)根据我的经验,没有可用的 express.js 中间件,我发现的解决方案需要在您的 http 服务器上监听升级事件并在它到达 ws 路由之前阻止对您的套接字连接的访问​​。

2) 您的浏览器将不允许在客户端的 websocket 连接期间设置额外的标头。它将通过 cookie 发送,因此您可以使用 express-session 首先在您的服务器上授权用户,将在浏览器上设置一个 cookie,该 cookie 将在 websocket 连接期间发送。

3)您可以在此答案中执行拦截(并可能拒绝)网络套接字升级请求从那里复制代码以供您自己阅读。

**wsHttpServer**.on('upgrade', function (req, socket, head) {
      var validationResult = validateCookie(req.headers.cookie);
      if (validationResult) {
        //...
      } else {
        socket.write('HTTP/1.1 401 Web Socket Protocol Handshake\r\n' +
                     'Upgrade: WebSocket\r\n' +
                     'Connection: Upgrade\r\n' +
                     '\r\n');
                     socket.close();
                     socket.destroy();
                     return;
      }
      //...
    });
Run Code Online (Sandbox Code Playgroud)