使用 Socket.IO 进行授权和握手

Posted

技术标签:

【中文标题】使用 Socket.IO 进行授权和握手【英文标题】:Authorizing and handshaking with Socket.IO 【发布时间】:2013-10-07 01:29:59 【问题描述】:

我想知道 Socket.IO 中授权和握手的主要功能是什么。我已经在 GitHub 上阅读了他们的 wiki 和 authorizing guide,但我仍然不明白以下内容:

    Socket.io 中的授权是如何工作的? Socket.IO 中的握手是什么? 我可以向handshakeData 对象添加任何内容吗?

希望你能回答我的问题。谢谢。

【问题讨论】:

【参考方案1】:

编辑: 在 Socket.IO 1.0 中,现在使用中间件。授权可以这样完成:

io.use(function(socket, next) 
  var handshake = socket.request;
  next();
);

如果您需要拒绝套接字,只需将错误对象传递给next() 回调。命名空间也可以做同样的事情:

io.of('/namespace').use(function(socket, next) 
  var handshake = socket.request;
  next();
);

Socket.IO 中的授权是通过一个函数运行的,该函数由回调传递的布尔值决定。每次连接尝试握手时都会运行此函数,如下所示:

io.set('authorization', function (handshake, callback) 
  callback(null, true);
);

函数callback() 接受两个参数。第一个是错误原因(如果有),第二个参数是决定客户端是否可以连接的布尔值。默认情况下是没有授权的,所以场景如上面的代码示例所示,正在连接的套接字被允许通过true

Socket.IO 中的握手与任何其他与信息技术相关的握手一样。这是协商的过程,在 Socket.IO 的情况下,它决定客户端是否可以连接,如果不能连接,则拒绝连接。握手是通过 XHR 或 JSONP 请求启动的,在未指定授权时不会做太多事情,但对 handshake 数据对象中传递的数据很有帮助。

要回答您的最后一个问题,是的,您可以在 handshake 对象中添加任何内容。该对象是对socket.handshake 对象的同一个变量引用,它允许您执行以下操作:

io.set('authorization', function (handshake, callback) 
  handshake.foo = 'bar';
  callback(null, true);
);

io.sockets.on('connection', function(socket) 
  console.log(socket.handshake.foo); // bar
);

这非常有用,因为您可以存储基于套接字的属性。一个常见的用途是使用 Express 框架,其中可以根据 Socket.IO 传递的 cookie 识别会话 ID,然后可以识别匹配的会话。

【讨论】:

谢谢兄弟。这就是我正在寻找的答案。 :) 这值得更多的喜欢。握手可以通过 socket.handshake 在套接字事件中获得这一显而易见的事实非常有用。 如果我打电话给next(new Error('Forbidden')); - 我如何才能获得有关我的连接在客户端被拒绝的信息?我不能从中间件 .emit() 因为next(new Error('')) 拒绝进一步通信。 有点晚了,但是您可以在客户端套接字上监听error 事件,因为如果调用next(new Error("Forbidden")),服务器会向客户端发送错误消息。【参考方案2】:

从 Socket.io 1.0 开始,虽然有向后兼容性,但建议使用“io.use()”来添加您的 ad-hoc 中间件,所以在 Node Server 端:

io.use(function(socket, next)
  var joinServerParameters = JSON.parse(socket.handshake.query.joinServerParameters);
  if (joinServerParameters.token == "xxx" )
    next();          
   else 
    //next(new Error('Authentication error'));                  
  
  return;       
);

在客户端,要将您自己的属性添加到握手中,如下所示:

var joinServerParameters =  token: "xxx"   ;    
var socket = io.connect('url' , query: 'joinServerParameters=' + JSON.stringify(joinServerParameters)  );

【讨论】:

【参考方案3】:

现在我正在使用这个简单的方法:

io.set('authorization', function (handshakeData, accept) 
  var domain = handshakeData.headers.referer.replace('http://','').replace('https://','').split(/[/?#]/)[0];
  if('myDomain.com'==domain)
    accept(null, true);
  else 
    return accept('Deny', false);
);

【讨论】:

【参考方案4】:

在这种情况下

io.set('authorization', function (handshake, callback) 
    handshake.foo = 'bar';
    callback(null, true);
);

io.sockets.on('connection', function(socket) 
    console.log(socket.handshake.foo); // bar
);

socket.handshake.foo 会给出 undefined

我们需要在这里调用 socket.request.foo 以获得正确的值

有人误导了我们,因为 io auth 中间件采用以下 PROPER NAMES 的 2 个参数(请求、回调) 而不是(握手、回调) PS:idk 可能以前的 io 版本有第二种情况 :)

io.set('authorization', function (request, callback) 
    request.foo = 'bar';
    callback(null, true);
);

【讨论】:

io.set 方法在版本 1.1 中被删除了 那么有什么选择呢?我正在使用 2.3.0,它仍然有效 它有效,但已弃用。使用中间件。 socket.io/docs/migrating-from-0-9/#Authentication-differences【参考方案5】:

我知道为时已晚,但我想在我发现关于使用 socket.io 的握手授权的非常好的文章中添加信息。

socket.io authorization

【讨论】:

以上是关于使用 Socket.IO 进行授权和握手的主要内容,如果未能解决你的问题,请参考以下文章

PHP + socket.io(会话、授权和安全问题)

使用 Redis 和 Socket.io 进行用户认证

Gottox socket.io-java-client“握手时出错”空指针异常

socket.io 握手返回错误“传输未知”

如何通过 socks5 代理使用 JavaScript socket.io-client 库?

Socket.io - 失败:连接在收到握手响应之前关闭