Authentication 套接字建立后的socket.io身份验证

Authentication 套接字建立后的socket.io身份验证,authentication,node.js,websocket,socket.io,Authentication,Node.js,Websocket,Socket.io,我正在做一个小型多人游戏。我想介绍一下身份验证。我正在使用Node.js和Socket.io 当用户到达主页时——我希望他们加入游戏,无论他们是否登录——但他们将无法在其中执行任何操作(仅观看) 然后,我如何在已经打开的套接字上对用户进行身份验证 如果他们离开网站回来,我还能保持身份验证吗?您可以通过web套接字传递cookie吗 编辑 进一步回答我的问题。我的一个可能想法是提供websocket连接,然后当他们尝试登录时,它将用户名和密码作为消息传递给websocket client.on('

我正在做一个小型多人游戏。我想介绍一下身份验证。我正在使用Node.js和Socket.io

当用户到达主页时——我希望他们加入游戏,无论他们是否登录——但他们将无法在其中执行任何操作(仅观看)

然后,我如何在已经打开的套接字上对用户进行身份验证

如果他们离开网站回来,我还能保持身份验证吗?您可以通过web套接字传递cookie吗

编辑

进一步回答我的问题。我的一个可能想法是提供websocket连接,然后当他们尝试登录时,它将用户名和密码作为消息传递给websocket

client.on('onLogin', loginfunction);
然后,我可以获取用户名和密码,对照数据库进行检查,然后获取套接字的会话ID,并将其传递到某个地方,表示会话已通过该用户的身份验证

这安全吗?我还可以在套接字上实现cookie,这样他们就可以回来了吗?在socket.io中是否有方法声明套接字现在已通过身份验证,而不是手动检查收到的每条消息


干杯

克里斯,我不能回答,因为我不是socket.io方面的专家,但我可以尝试为您指出另一个可以帮助您的方向,并占用一些开发时间

但首先,我要声明:我为Realtime.co工作,不想做任何形式的广告。我与开发人员密切合作,我只是想通过为您的问题提供开箱即用的解决方案来帮助您。而且,作为一名玩家,我不能不尝试帮助人们把他们的游戏拿出来

Realtime使用一个身份验证/授权层,您可以在该层中为通道提供用户读/写权限。当用户进入网站时,您可以授予他们对游戏频道的只读权限,一旦他们登录,您就可以授予他们写入权限。这可以通过执行身份验证post和重新连接到服务器(都可以在客户端完成)轻松完成。不过,为了提高安全性,我会在服务器端这样做

Realtime有一个Node.js API,因此您可以轻松地将其与服务器集成。由于它也有许多其他平台(包括移动平台)的API,并且它们都以相同的方式工作,因此您实际上可以让您的游戏在同一通信层的多个平台上工作,同时完全控制通道

谢谢你的阅读

编辑:


您可以阅读此处的文档以了解更多信息:

这其实并不难,但您的做法是错误的。有几件事:

  • 无法使用socket.io设置cookie;但是,您可以随时获取任何已连接客户端的cookie值。为了设置cookie,您必须发送一个新的http响应,这意味着用户必须首先发送一个新的http请求(也称为刷新或转到一个新页面,这里听起来您不可能这样做)

  • 是:socket.io是安全的(任何传输的数据都可以安全传输)

  • 因此,您可以执行以下操作:

    在用户的初始连接上,创建具有唯一会话ID的cookie,例如从Express的会话中间件生成的cookie。您需要将它们配置为不会在会话结束时过期(否则,它将在它们关闭浏览器时过期)

    接下来,您应该创建一个对象来存储cookie会话ID。每次设置新的connect.sid cookie时,将默认值false存储在新对象中(表示用户已通过会话验证,但未通过登录验证)

    在用户登录时,将套接字发送到服务器,然后您可以在服务器上验证登录凭据,并随后更新您创建的会话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
        });
    
    });
    

    Socket.io有一个可传递的选项。可以使用它从客户端传递令牌。服务器将使用所需的身份验证算法解密令牌并获取
    用户id

    socket.js

    import io from 'socket.io-client';
    
    export const socket = io('https://remote-url');
    
    export const socketAuth = () => {
      socket.io.disconnect();  //This uses the same socket and disconnect with the server. 
      socket.io.opts.extraHeaders = {
        'x-auth-token': JSON.parse(window.localStorage.getItem('auth-token')),
      };
      socket.io.opts.transportOptions = {
        polling: {
          extraHeaders: {
            'x-auth-token': JSON.parse(window.localStorage.getItem('auth-token')),
          },
        },
      };  
      socket.io.open(); //Opens up a new connection with `x-auth-token` in headers
    
    };
    
    client.js

      import { socket, socketAuth } from 'utils/socket';
      socket.on('unauthenticated-messages', () => {
        someAction();
      });
    
      //After user logs in successfully
      socketAuth();
    
      socket.on('authenticated-messages', () => {
        someAction();
      });
    

    请参阅如何对socket.io会话进行身份验证。是的,我已经阅读了这篇文章。虽然我很乐意设置cookie,但如果套接字已经打开,它不允许登录同一页面。如果用户禁用了Cookie,可能也会受到影响?在建立连接并完成握手后,是否有办法将连接设置为在socket.io中经过身份验证?用户可以在准备好连接现有连接时提供登录详细信息,服务器可以验证并返回唯一的会话ID。然后客户端javascript可以保存cookie以供将来使用。是否希望能够在同一页面上重新登录用户?99.99%的用户启用了cookie。如果有什么问题的话,他们很可能会禁用Javascript。如果我错了,请纠正我,但通常不会考虑永不过期的会话吗insecure@Mozoby我的代码将cookie设置为在经过一定时间后过期-它不是无限期的。我这样做是因为最初的问题似乎表明返回的用户仍然应该登录,这意味着我不能像默认情况下那样让cookie在浏览器关闭时过期。