我正在开发一款小型多人游戏。我想介绍身份验证。我正在使用 Node.js 和 Socket.io。
当用户到达主页时——无论他们是否登录,我都希望他们加入游戏——但他们将无法在其中做任何事情(只能观看)。
然后我该如何在已经打开的套接字上对用户进行身份验证?
如果他们离开网站然后回来,我还能保持身份验证吗?可以通过网络套接字传递 cookie 吗?
编辑
进一步我的问题。我的一个可能想法是提供 websocket 连接,然后当他们尝试登录时,它将用户名和密码作为消息传递给 websocket。
client.on('onLogin', loginfunction);
然后我可以获取用户名和密码,检查数据库,然后获取套接字的 session ID 并将其传递到某个地方,以说明 session 已通过该用户的身份验证。
这安全吗?我还能在套接字上实现一个 cookie 以便他们可以回来吗? socket.io 中是否有任何方法表明套接字现在已通过身份验证,而不是手动检查收到的每条消息?
干杯
最佳答案
这实际上并不太难,但是您以错误的方式接近它。几件事:
你不能用socket.io设置一个cookie;但是,您可以随时获取任何已连接客户端的 cookie 值。为了设置 cookie,您必须发送一个新的 http 响应,这意味着用户必须首先发送一个新的 http 请求(也就是刷新或转到新页面,这听起来对您来说是不可能的)。
是的:socket.io 是安全的(在任何传输数据都可以的范围内)。
因此,您可以执行以下操作:
在用户的初始连接上,创建一个具有唯一 session ID 的 cookie,例如从 Express 的 session 中间件生成的那些。不过,您需要将它们配置为不会在 session 结束时过期(否则它们会在关闭浏览器后立即过期)。
接下来,您应该创建一个对象来存储 cookie session ID。每次设置新的 connect.sid cookie 时,将默认值 false 存储在新对象中(意味着用户已通过 session 进行身份验证,但未通过登录)
在用户登录时,向服务器发送一个套接字发射,然后您可以在服务器上验证登录凭据,然后更新您创建的 session id 对象以读取当前套接字 id 的 true(登录)。
现在,当接收到一个新的 http 请求时,读取 cookie.sid,并检查它在您的对象中的值是否为 true。
它应该如下所示:
var express = require('express'),
http = require('http'),
cookie = require('cookie');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
app.use(express.cookieParser());
app.use(express.session({
secret: 'secret_pw',
store: sessionStore,
cookie: {
secure: true,
expires: new Date(Date.now() + 60 * 1000), //setting cookie to not expire on session end
maxAge: 60 * 1000,
key: 'connect.sid'
}
}));
var sessionobj = {}; //This is important; it will contain your connect.sid IDs.
//io.set('authorization'...etc. here to authorize socket connection and ensure legitimacy
app.get("/*", function(req, res, next){
if(sessionobj[req.cookies['connect.sid']]){
if(sessionobj[req.cookies['connect.sid']].login == true){
//Authenticated AND Logged in
}
else{
//authenticated but not logged in
}
}
else{
//not authenticated
}
});
io.sockets.on('connection', function(socket){
sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].login = false;
sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid'].socketid = socket.id;
socket.on('login', function(data){
//DB Call, where you authenticate login
//on callback (if login is successful):
sessionobj[cookie.parse(socket.handshake.headers.cookie)['connect.sid']] = true;
});
socket.on('disconnect', function(data){
//any cleanup actions you may want
});
});
关于authentication - 建立套接字后的socket.io身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8754849/