60

所以我有一个运行 node js 的应用程序,socket.io 作为后端,普通的 javascript 作为前端。我的应用程序有一个登录系统,目前它只是让客户端在连接后立即发送其登录数据。

现在我认为将登录数据与握手数据一起发送会更好,所以我可以直接让用户在连接时登录(而不是在建立连接后)分别在登录数据无效时拒绝授权。

我认为最好将我的附加数据放在握手数据的标题部分中,所以有什么想法可以做到这一点吗?(如果可能,不必修改 socket.io,但如果这是我可以忍受的唯一方法)

4

7 回答 7

147

1.0正如许多评论在其发布中更改的 Socket.IO API 下面所指出的那样。现在应该通过中间件功能完成身份验证,请参阅“身份验证差异”@ http://socket.io/docs/migrating-from-0-9/#authentication-differences。由于旧文档似乎已经消失,我将为停留在 <1.0 的任何人提供我的原始答案。

1.0 及更高版本:

客户端:

//The query member of the options object is passed to the server on connection and parsed as a CGI style Querystring.
var socket = io("http://127.0.0.1:3000/", { query: "foo=bar" });

服务器端:

io.use(function(socket, next){
    console.log("Query: ", socket.handshake.query);
    // return the result of next() to accept the connection.
    if (socket.handshake.query.foo == "bar") {
        return next();
    }
    // call next() with an Error if you need to reject the connection.
    next(new Error('Authentication error'));
});

1.0前

您可以将第二个参数中的 query: param 传递给客户端的 connect(),该参数将在服务器上以授权方法可用。

我刚刚在测试它。在客户端我有:

var c = io.connect('http://127.0.0.1:3000/', { query: "foo=bar" });

在服务器上:

io.set('authorization', function (handshakeData, cb) {
    console.log('Auth: ', handshakeData.query);
    cb(null, true);
});

然后服务器上的输出如下所示:

:!node node_app/main.js
   info  - socket.io started
Auth:  { foo: 'bar', t: '1355859917678' }

更新

3.x 及更高版本

您可以使用 auth 参数作为客户端中 connect() 的第二个参数传递身份验证有效负载。

客户端:

io.connect("http://127.0.0.1:3000/", {
    auth: {
      token: "AuthToken",
    },
  }),

在服务器端,您可以使用socket.handshake.auth.token

服务器端:

io.use(function(socket, next){
    console.log(socket.handshake.auth.token)
    next()
});
于 2012-12-18T19:48:54.470 回答
19

这在 v1.0.0 中已更改。请参阅迁移文档

基本上,

io.set('authorization', function (handshakeData, callback) {
  // make sure the handshake data looks good
  callback(null, true); // error first, 'authorized' boolean second 
});

变成:

  io.use(function(socket, next) {
  var handshakeData = socket.request;
  // make sure the handshake data looks good as before
  // if error do this:
    // next(new Error('not authorized');
  // else just call next
  next();
});
于 2014-09-24T14:12:22.423 回答
10

对于 socket.io v1.2.1 使用这个:

io.use(function (socket, next) {
  var handshake = socket.handshake;
  console.log(handshake.query);
  next();
});
于 2014-12-22T15:31:52.207 回答
7

这是我将查询数据发送到 nodejs 和 server.io 服务器客户端的代码。

var socket = io.connect(window.location.origin, { query: 'loggeduser=user1' });

io.sockets.on('connection', function (socket) {
    var endp = socket.manager.handshaken[socket.id].address;
    console.log("query... " + socket.manager.handshaken[socket.id].query.user);
}
于 2014-03-29T20:07:28.067 回答
1

也许 api 已更改,但我做了以下操作以获取服务器的额外信息。

// client
io.connect('localhost:8080', { query: 'foo=bar', extra: 'extra'});

// server
io.use(function(sock, next) {
  var handshakeData = sock.request;
  console.log('_query:', handshakeData._query);
  console.log('extra:', handshakeData.extra);
  next();
});

印刷

_query: { foo: 'bar',
  EIO: '3',
  transport: 'polling',
  t: '1424932455409-0' }
extra: undefined

如果有人知道如何通过不在查询参数中的握手将数据从客户端获取到服务器,请告诉我。

更新我后来遇到了这个语法的问题

io.connect('localhost:8080?foo=bar');

是我目前正在使用的。

于 2015-02-26T06:39:20.940 回答
1

旧线程,但假设您将 jwt 令牌/会话 ID 存储在会话 cookie(标准内容)中,默认情况下,当我注意到握手时(socket.io-client),默认情况下它会传递给服务器。通过 cookie 获取握手的身份验证信息(通过中间件或 on.connection)有什么问题吗?例如。

io.on('connection', function(socket) {
  // assuming base64url token
  const cookieStr = socket.handshake.headers.cookie
  const matchRes =
    cookieStr == null
      ? false
      : cookieStr.match(/my-auth-token=([a-zA-Z0-9_.-]+)/)
  if (matchRes) {
    // verify your jwt...
    if ( tokenIsGood(matchRes[1]) {
      // handle authenticated new socket
    } else {
      socket.emit('AUTH_ERR_LOGOUT')
      socket.disconnect()
    }
  } else {
    socket.emit('AUTH_ERR_LOGOUT')
    socket.disconnect()
  }
}

我现在将它用于一个项目,它工作正常。

于 2019-01-26T06:51:05.310 回答
0

我发现看到.loggeduser有点问题

io.sockets.on('connection', function (socket) {
    var endp = socket.manager.handshaken[socket.id].address;
    console.log("query... " + socket.manager.handshaken[socket.id].query.loggeduser);
                                                                         // ↑ here
}
于 2014-05-27T01:16:02.567 回答