Authentication Socket.IO身份验证

Authentication Socket.IO身份验证,authentication,node.js,express,socket.io,Authentication,Node.js,Express,Socket.io,我尝试在Node.js中使用Socket.IO,并尝试允许服务器为每个Socket.IO客户端提供一个标识。由于套接字代码不在http服务器代码的范围内,因此无法轻松访问发送的请求信息,因此我假设需要在连接期间发送它。最好的方法是什么 1) 通过Socket.IO向服务器获取有关谁正在连接的信息 2) 验证他们所说的身份(我目前正在使用Express,如果这能让事情变得更简单的话)使用connect redis,并将redis作为所有已验证用户的会话存储。确保在身份验证时将密钥(通常为req.s

我尝试在Node.js中使用Socket.IO,并尝试允许服务器为每个Socket.IO客户端提供一个标识。由于套接字代码不在http服务器代码的范围内,因此无法轻松访问发送的请求信息,因此我假设需要在连接期间发送它。最好的方法是什么

1) 通过Socket.IO向服务器获取有关谁正在连接的信息


2) 验证他们所说的身份(我目前正在使用Express,如果这能让事情变得更简单的话)

使用connect redis,并将redis作为所有已验证用户的会话存储。确保在身份验证时将密钥(通常为req.sessionID)发送到客户端。让客户端将此密钥存储在cookie中

在socket connect上(或以后任何时候),从cookie中获取此密钥并将其发送回服务器。使用此键在redis中获取会话信息。(获取密钥)

例如:

服务器端(以redis作为会话存储):

请求会话.重新生成。。。
res.send({rediskey:req.sessionID});
客户端:

//将密钥存储在cookie中
SetCookie('rediskey',)//http://msdn.microsoft.com/en-us/library/ms533693(v=vs.85).aspx
//然后,当连接套接字时,从document.cookie中获取rediskey并将其发送回服务器
var socket=新io.socket();
socket.on('connect',function(){
var rediskey=GetCookie('rediskey')//http://msdn.microsoft.com/en-us/library/ms533693(v=vs.85).aspx
send({rediskey:rediskey});
});
服务器端:

//in io.on('connection')
io.on('connection', function(client) {
  client.on('message', function(message) {

    if(message.rediskey) {
      //fetch session info from redis
      redisclient.get(message.rediskey, function(e, c) {
        client.user_logged_in = c.username;
      });
    }

  });
});
我也喜欢你的方式

生成一个唯一的套接字id,并 由推送器发送到浏览器。这是 通过电子邮件发送到您的应用程序(1) 授权用户的AJAX请求 根据您的 现有的认证系统。如果 成功的应用程序将返回一个 将授权字符串添加到浏览器 和你签的是Pusher机密。这是 发送至腹板箱上方的推进器, 这就完成了授权(2) 如果授权字符串匹配

因为,
socket.io
对每个套接字都有唯一的套接字id

socket.on('connect', function() {
        console.log(socket.transport.sessionid);
});
他们过去常常授权用户

我还没有将其镜像到socket.io,但我认为这可能是一个非常有趣的概念

//server side

io.sockets.on('connection', function (con) {
  console.log(con.id)
})

//client side

var io = io.connect('http://...')

console.log(io.sessionid)
本文()展示了如何

  • 在Redis中存储HTTP服务器的会话(使用Predis)
  • 通过cookie中发送的会话id从node.js中的Redis获取这些会话
使用此代码,您也可以在socket.io中获取它们

var io = require('socket.io').listen(8081);
var cookie = require('cookie');
var redis = require('redis'), client = redis.createClient();
io.sockets.on('connection', function (socket) {
    var cookies = cookie.parse(socket.handshake.headers['cookie']);
    console.log(cookies.PHPSESSID);
    client.get('sessions/' + cookies.PHPSESSID, function(err, reply) {
        console.log(JSON.parse(reply));
    });
});

我知道这有点老了,但是对于未来的读者来说,除了解析cookie和从存储中检索会话(例如),你也可以考虑基于令牌的方法。 在本例中,我使用非常标准的JSON Web标记。您必须向客户端页面提供令牌,在本例中,想象一个返回JWT的身份验证端点:

var jwt = require('jsonwebtoken');
// other requires

app.post('/login', function (req, res) {

  // TODO: validate the actual user user
  var profile = {
    first_name: 'John',
    last_name: 'Doe',
    email: 'john@doe.com',
    id: 123
  };

  // we are sending the profile in the token
  var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });

  res.json({token: token});
});
现在,您的socket.io服务器可以按如下方式配置:

var socketioJwt = require('socketio-jwt');

var sio = socketIo.listen(server);

sio.set('authorization', socketioJwt.authorize({
  secret: jwtSecret,
  handshake: true
}));

sio.sockets
  .on('connection', function (socket) {
     console.log(socket.handshake.decoded_token.email, 'has joined');
     //socket.on('event');
  });
socket.io-jwt中间件需要查询字符串中的令牌,因此从客户端连接时只需附加它:

var socket = io.connect('', {
  query: 'token=' + token
});

我对这个方法和cookies做了更详细的解释。

在c/s之间使用session和Redis

服务器端

io.use(函数(套接字,下一个){
//到达这里会话id
log(socket.handshake.headers.cookie);并从redis会话数据进行匹配
next();
});

以下是我尝试让以下工作正常进行的步骤:

  • 快车:4.14
  • socket.io:1.5
  • passport(使用会话):0.3
  • redis:2.6(处理会话的数据结构非常快;但您也可以使用其他类似MongoDB的数据结构。不过,我建议您将其用于会话数据+MongoDB来存储其他持久数据,如用户)
由于您可能还想添加一些API请求,我们还将使用http包使http和Web套接字在同一端口中工作


server.js 以下摘录仅包括设置以前的技术所需的所有内容。您可以看到我在一个项目中使用的完整的server.js版本

从“http”导入http;
从“快递”进口快递;
从“护照”进口护照;
从“redis”导入{createClient as createRedisClient};
从“连接redis”导入connectRedis;
从“socket.io”导入Socketio;
//您自己的套接字处理程序文件,它是可选的。解释如下。
从“./sockets”导入socketConnectionHandler;
//关于Redis会话数据结构的配置。
const redisClient=createRedisClient();
const redistore=connectRedis(会话);
const dbSession=new redistore({
客户:我的客户,
主机:“localhost”,
港口:27017,
前缀:'stackoverflow_382;',
disableTTL:对
});
//让我们将Express配置为使用Redis存储来处理
//会议也是如此。您可能需要Express来处理您的问题
//会话,并与socket.io共享相同的存储
//确实如此(即用于处理AJAX登录)。
const session=会话({
雷萨夫:是的,
saveUninitialized:true,
key:'SID',//这将用于会话cookie标识符
秘密:“秘密密钥”,
门店:dbSession
});
应用程序使用(会话);
//让我们使用他们的中间件初始化passport,这可以
//一切几乎都是自动完成的。(您必须配置登录
///自行注册策略(参见参考文献1)
app.use(passport.initialize());
app.use(passport.session());
//Socket.IO
常量io=Socketio(服务器);
io.use((套接字,下一个)=>{
会话(socket.handshake,{},next);
});
io.on('connection',socketConnectionHandler);
//socket.io已准备就绪;请记住^this^变量只是
//我们为自己的socket.io处理程序文件指定的名称(已解释)
//就在这之后)。
//启动服务器。此wil