【问题标题】:socket.io-client how to set request header when making connectionsocket.io-client 建立连接时如何设置请求标头
【发布时间】:2014-06-17 20:10:39
【问题描述】:

我正在尝试在 socket.io 客户端发出连接请求时设置一个 http 标头。有没有办法做到这一点?

这是我正在做的事情:

// server side
var io = socketio(server);

io.use(function (socket, next) {
  // authorize using authorization header in socket.request.headers
});

// client side
var socket = io();  // i'm trying to set an authorization header in this http reqeust

有什么想法吗?谢谢。

【问题讨论】:

  • 当socket客户端发出请求时,它已经有请求头了。你是说你想改变那些,或者你只是想从套接字客户端发送一些令牌并基于你想要授权客户端的那些令牌???
  • 我想在标头中发送一个令牌。 @MOmayr
  • 您可以在查询字符串中发送该令牌并在授权功能中检查它。我应该给你举个例子吗?
  • @MOmayr 谢谢。这就是我目前正在做的事情。但是将令牌放在标题中是我想做的。因为这样我可以将我的身份验证中间件重用于 socket.io 连接请求。
  • 好吧,我认为你必须为此挖掘 socket.io。但是您可以在授权功能中附加一个带有套接字的对象,然后在 io.connection 事件中使用它。

标签: node.js socket.io jwt


【解决方案1】:

由于某种原因,只有当套接字服务器也是 socket.io 时才会接收到这些请求标头。 例如,如果我连接到 python Websockets 服务器,我就没有运气进行身份验证。

对我有用的唯一解决方案是使用不同的 WebSocket 客户端,例如,ws 工作正常。

import WebSocket from 'ws';

const socket = new WebSocket('wss://example.com/path', {
      headers: {
            Authorization: 'token'
         },
 });

【讨论】:

  • 有没有办法处理ws does not work in the browser. Browser clients must use the native WebSocket object错误?
【解决方案2】:

有一种新方法可以做到这一点:https://socket.io/docs/v3/middlewares/。查看“发送凭据”部分。

// client
const socket = io(server, {
    transports: ['websocket', 'polling', 'flashsocket'],
    auth: {
        token: 'abc'
    }
});

// server
io.use((socket, next) => {
    const token = socket.handshake.auth.token;
    if (isValidJwt(token)){
        next();
    }else{
        next(new Error("Socket authentication error"));
    }
});

async function isValidJwt(token){
    jwt.verify(token, secrets.jwt, function(err, decoded) {
        if (err){
            console.log(err);
            return false;
        }else{
            //console.log(decoded);
            return true;
        }
    });
}

【讨论】:

  • 完美。这很好用,是今天最新的答案。
【解决方案3】:

简短回答:这是基于规范的 impossiburu...如果您只需要尽早传递信息...为什么不查询参数?

socket = io('localhost:5000', {
      path: '/mySocketPath',
      transports: ['websocket'],
      query: {
        token:'some-token-value'
      }
})

见@satpal-07 https://github.com/socketio/socket.io-client/issues/1356#issuecomment-810023635

【讨论】:

  • 非常简单:因为 URL 长度有限,可能会导致非常烦人的问题。
【解决方案4】:

以下信息自 socket.io 1.0 以来已被弃用

有两种授权方法:全局或命名空间(想想路由)。使用io.set('authorization', function (handshakeData, callback) 配置调用在服务器上设置全局方法。

handshakeData 对象包含以下信息:

{
   headers: req.headers       // <Object> the headers of the request
 , time: (new Date) +''       // <String> date time of the connection
 , address: socket.address()  // <Object> remoteAddress and remotePort object
 , xdomain: !!headers.origin  // <Boolean> was it a cross domain request?
 , secure: socket.secure      // <Boolean> https connection
 , issued: +date              // <Number> EPOCH of when the handshake was created
 , url: request.url          // <String> the entrance path of the request
 , query: data.query          // <Object> the result of url.parse().query or a empty object
}

以上信息和更深入的解释可以在这个 documentation page上找到。

【讨论】:

  • io.set('authorization') 实际上在 1.0 中已被弃用:socket.io/docs/migrating-from-0-9
  • 伙计们...无需反对。我添加了编辑,这是不推荐使用的信息。答案来自 2014 年。
【解决方案5】:

“transportOptions”选项可用于在 socket.io 请求中发送额外的标头。我也在这里解释过:-

Node.js + Socket.io | Set custom headers on the server

【讨论】:

    【解决方案6】:

    截至版本 2.0.0 / 2017-01-22 engine.io-client supports

    [feature] Allow extraHeaders to be set for browser clients in XHR requests (#519)
    

    但是此时 socket.io-client 尚未更新以支持此功能,因此几天后此传奇可能会结束,直到那时使用以下说明:https://facundoolano.wordpress.com/2014/10/11/better-authentication-for-socket-io-no-query-strings/

    【讨论】:

      【解决方案7】:

      如果您使用的是 socket.io-client >= 1.4,则可以使用 extraHeaders 选项。

      例如:

      var socket = io("http://localhost", {
        extraHeaders: {
          Authorization: "Bearer authorization_token_here"
        }
      });
      

      engine.io-client,是socket.io-client的后端,introduced extraHeaders support on 2015-11-28

      【讨论】:

      • 虽然这似乎是一个不错的选择,但它在使用 NodeJS 客户端时有效,但在浏览器中无效。它在自述文件中说明了这一点,可能是上面 bakavic 答案中第一个链接的 b/c(并非所有传输都允许设置自定义标头)
      • 由于一个错误,截至昨天某些浏览器不支持它,我已经修复它:)
      • 太棒了,那你如何获取服务器端的标头?
      • 不幸的是,extraHeaders 仅适用于轮询模式而不适用于 websocket...
      • 仅当连接通过 http(s) 时才提供标头,这对于初始握手始终是正确的。之后,如果客户端/服务器“升级”到 ws(s),则没有可用的标头。您将不得不在数据包中传递身份验证数据。
      【解决方案8】:

      看起来像client doesn't support setting headers,因为并非所有传输都允许设置标头。

      facundoolano 的 post 详细介绍了一种不需要将身份验证令牌放在查询字符串中的身份验证解决方法。

      他的解决方法模块可以在https://github.com/invisiblejs/socketio-auth找到。

      让我想知道为什么在服务器端,socket.io 允许访问请求标头...

      【讨论】:

      • Socket.io 握手(即使对于 WebSockets)从常规 REST 调用开始并进一步提升到 WebSocket 协议,所以答案似乎是错误的,另一方面,如果您使用的是 HTTP 请求标头,那么这应该有效很好……
      猜你喜欢
      • 2011-12-11
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 2023-03-18
      • 2019-01-26
      • 2018-03-30
      • 2020-10-09
      • 2011-07-23
      相关资源
      最近更新 更多