Socket.io-client: 允许 socket.handshake.query 成为一个函数

创建于 2017-05-22  ·  9评论  ·  资料来源: socketio/socket.io-client

你想要:

  • [x] 报告错误
  • [ ] 请求一个功能

当前行为

socket.handshake.query当前允许在connect上设置数据,但在触发reconnect之前不能通过引用更新。 这会在使用刷新令牌授权套接字连接时出现问题。

重现步骤(如果当前行为是错误)

//client
io.connect("wss://socket.server.com", {
   query : {
      token:"something dynamic"
   }
});

如果服务器重新启动并且客户端reconnect ,则在重新授权套接字时令牌可能已过时。

//server
io.use(function(socket, next) {
   var query = socket.handshake.query;
   if(isValidToken(query.token)){
      next();//will never fire if the token has been updated
   }
});

预期行为

允许查询为function

io.connect("wss://socket.server.com", {
   query : function(){
      return {
         token:"something dynamic"
      }
   }
});

设置

  • socket.io 版本:2.0.1

怎么修

在当前的 Socket 构造函数中:

if (opts && opts.query) {
   this.query = opts.query;
}

可以改成这样:

if(opts && opts.query) {
   this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}

最有用的评论

@reeltimedoktor目前您应该能够在reconnect_attempt事件上更新query对象:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

所有9条评论

+1
修复错误 #1086 也应该可以解决您的问题。 成功连接后更改查询选项适用于较旧的 socket.io-client 版本,但在当前版本中,对查询对象的引用丢失了:(

@reeltimedoktor目前您应该能够在reconnect_attempt事件上更新query对象:

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

@darrachequesne的解决方案似乎对我不起作用:(

我在客户端的socket.io-client版本2.3.0上,使用socket.io版本2.3.0的节点服务器。

在客户端我这样做:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken();
      socket.io.opts.query = {
        token: latestToken,
      };
    });

然后服务器使用传递给io.use()的中间件对令牌进行身份验证(当套接字连接或重新连接时应该触发,afaik?)。

目前服务器身份验证无法重新连接,说令牌已过期 - 似乎新令牌没有正确分配给socket.io.opts.query.token - 任何想法为什么?

谢谢 :)

更新:似乎在存储身份验证令牌的套接字对象中有很多不同的地方,例如socket.io.engine.query.tokensocket.io.engine.transport.query.token 。 当您设置socket.io.opts.query.token时,这些不会自动填充。 但是,更改这些仍然不会影响服务器“看到”的内容——它仍然只能看到旧令牌。

该令牌似乎也作为 URL 参数包含在套接字对象的某些 url 字段中。 也许这些也需要更新?

进一步调查后,似乎设置令牌上的socket.io.opts.query.token足以改变令牌进行再认证的重新连接-别的东西似乎是我的应用程序的问题,也许是与火力的身份验证令牌生成。 因此,对于遇到此问题的任何其他人, @darrachequesne的解决方案有效!

好的,我想我已经修复了它 - 您需要确保在“reconnect_attempt”回调中同步获取新令牌,即不要这样做:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

似乎在设置新令牌之前已完成服务器端身份验证。 如果您同步获取令牌(通过提前获取并存储它,然后在侦听器回调中检索它),服务器会及时获取新的身份验证令牌以进行重新连接身份验证。

使用"socket.io-client": "3.0.4"我收到TS2341: Property 'opts' is private and only accessible within class 'Manager'.错误。 我正在使用"typescript": "4.1.3"
image

好的,我想我已经修复了它 - 您需要确保在“reconnect_attempt”回调中_同步_获取新令牌,即不要这样做:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

似乎在设置新令牌之前已完成服务器端身份验证。 如果您同步获取令牌(通过提前获取并存储它,然后在侦听器回调中检索它),服务器会及时获取新的身份验证令牌以进行重新连接身份验证。

我们有一个类似的问题。 但是我目前的解决方法是在身份验证失败时从服务器端转到disconnect 。 在客户端收到disconnect事件后,我们使用异步承诺调用重新构造查询/标头。 当它到达reconnecting事件时,它已经在查询/标题中具有新值。

对于未来的读者:

该行为query在Socket.IO V2选择是有点不可思议,因为它是在这两个使用:

  • 查询参数(对于 Manager 实例)
  • Socket.IO 握手(但仅适用于非默认命名空间)

所以我不确定我们如何以向后兼容的方式修复它......

请注意,这是在 Socket.IO v3 中修复的,因为您现在可以使用auth选项:

// plain object
const socket = io({
  auth: {
    token: "abc"
  }
});

// or with a function
const socket = io({
  auth: (cb) => {
    cb({
      token: "abc"
    });
  }
});

它也应该与async函数一起使用:

const socket = io({
  auth: async (cb) => {
    cb({
      token: "abc"
    });
  }
});

也可以看看:

此页面是否有帮助?
0 / 5 - 0 等级