如何告诉WebSocket客户端身份验证失败

6

我正在使用 (ws包) 在Node.js中提供WebSocket服务。我使用“on upgrade”事件来验证连接客户端,使用在URL参数中传递的令牌。根据这里的示例,如果令牌无效/缺失/过期,则使用以下(TypeScript)代码拒绝连接:

server.on('upgrade', async (req: Request, socket: Socket) => {
  // Make sure that we only handle WebSocket upgrade requests
  if (req.headers['upgrade'] !== 'websocket') {
    socket.destroy(new Error(`Expected headers upgrade == 'websocket', received ${req.headers['upgrade']}`));
    return;
  }
  if (_.get(this.config, 'security.enableAuth')) {
    logger.info('[socket] security: validating the session key parameter');
    const u = querystring.parse(req.url.substring(req.url.indexOf('?') + 1));
    if (!u.sessionKey) {
      logger.info('[debug] no session key found');
      socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
      socket.destroy();
      return;
    }
    const token = u.sessionKey as string;
    let result: AuthResult;
    try {
      result = await auth(token);
    } catch (err) {
      logger.warn('[socket] error validating session key:', err);
      socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
      socket.destroy();
      return;
    }
    // and so on...

除了客户端没有收到401消息以外,其他都可以正常工作,也没有任何内容能够告诉我连接失败的原因。Chrome网络选项卡没有显示任何已接收的消息,关闭事件代码为1006(CLOSE_ABNORMAL),没有其他信息。如何传递合理的错误代码或消息,以便客户端知道连接失败的原因?

请查看以下链接:https://dev59.com/TloV5IYBdhLWcg3wCrAn - gazdagergo
1个回答

5

似乎浏览器端无法处理401响应,尽管这看起来很奇怪。这使得在问题中采用的“推荐”方法的适用性受到限制,因为没有办法告诉客户端为什么握手被拒绝。写入 TCP 套接字的任何数据都将被浏览器丢弃(尽管可能会被不同的客户端使用)。在我的情况下,这个限制是无法接受的。与其拒绝握手,我会接受它,然后立即以适当的代码和原因关闭套接字:

this.wss.on('connection', async (ws: ExtendedWebSocket, req: Request) => {
logger.info('[socket] security: validating the session key parameter');
const u = querystring.parse(req.url.substring(req.url.indexOf('?') + 1));
if (!u.sessionKey) {
  logger.info('[debug] no session key found');
  ws.close(WS_CLOSE_CODES.CLOSE_POLICY_VIOLATION, 'Unauthorized'); // code=108
  return;
}
const token = u.sessionKey as string;
const result = await auth(token);
if (result.failed) {
  logger.warn(`[socket] invalid token (${token}) - auth failed`);
  ws.close(WS_CLOSE_CODES.CLOSE_POLICY_VIOLATION, 'Unauthorized');
  return;
}
// and so on...

相关且值得阅读:https://dev59.com/vGEi5IYBdhLWcg3wBX8t#50685387。看起来这种行为是设计上的(出于安全考虑)。接受/关闭的唯一问题是你现在向攻击者宣传了一个开放的WebSocket通道。 - Robert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接