是否可以仅在用户登录时连接 Socket.io?

Posted

技术标签:

【中文标题】是否可以仅在用户登录时连接 Socket.io?【英文标题】:Is it possible to connect Socket.io ONLY upon when user logs in? 【发布时间】:2021-03-02 01:50:23 【问题描述】:

我正在学习Socket.io 的基础知识,我只想在用户登录时实现连接。目前,官方的documentation 似乎并没有真正提到这种实现。我使用JWT 进行身份验证,使用Node.js 进行服务器端。

目前,Socket.io 在网站访问时连接:

const express = require('express');
const app = express();
const server = app.listen( process.env.PORT || 5555 );

const io = require('socket.io')(server, 
   cors: 
      origin: "*",
      methods: ["GET", "POST"]
   
);

io.on('connection', socket => 
   console.log('A client connected but not logged in yet.');
   
   socket.on('disconnect', () => 
      console.log('A client disconnected');
   );
);

我希望 Socket.io 仅在用户登录时连接:

/** Example Logic **/

if (user_is_logged_in) 
   const io = require('socket.io')(server, 
      cors: 
         origin: "*",
         methods: ["GET", "POST"]
      
   );

实现这一点的最佳方法是什么?还是有可能?谢谢。

【问题讨论】:

JWT 是否存储在客户端(例如 localstorage)? 不,服务器是公共的,需要您实现任何用户身份验证。您可以将 jwt 作为连接中的参数传递,然后在中间件中实现检查,就像在您的应用程序中一样 @Owl 是的,它通过 localStorage 存储在客户端。 你不应该使用 localstorage 来存储 jwt,它对 XSS 或 你的兄弟 窃取它不安全 see 只使用 http 安全 cookie IMO 可以将您的 JWT 存储在 localStorage 中,只要确保您避开用户输入(现代前端框架应该为您执行此操作),如果您将 JWT 存储在 cookie 中但您的网站存在 XSS 漏洞,无论如何,你注定要失败,“If your site runs a malicious script, it's game over anyway. They can just bind keydown events to inputs of type password and steal your user's authentication information that way (which is much, much worse than stealing a JWT auth token).”来自@LawrenceCherone 分享的问题的评论之一 【参考方案1】:

这样做的方法是在连接后检查用户是否登录。

在客户端

const jwt = getJWTFromLocalStorage(); // assume it returns undefined if user is not logged in
if (jwt) 
    const socket = io("http://example.com", 
        query: 
            token: jwt
        )
    ;

在服务器端

io.on('connection', socket => 
    const token = socket.handshake.query.token; // jwt token passed from client

    // authenticate
    try 
        if (!token) throw new Error("Token not found");
        jwt.verify(token, yourJWTSecret)
     catch (err) 
        // jwt verification failed
        socket.emit("authFailed") // emits event to client to let client know authentication failed, optional.
        socket.disconnect(); // disconnect client 
    
   
    socket.on('disconnect', () => 
        console.log('A client disconnected');
    );
);

请记住,从 URL 查询字符串传递的 JWT 是 not a safe method,我建议实现其他的身份验证,例如 this

【讨论】:

yup 或者socket.handshake.cookie如果使用cookies 是否可以从客户端发送数据而不是查询?所以也许像const socket = io('URL', someData: 'token value' ); 否,但您可以从.emit 传递数据,因此您可以在连接后在客户端调用socket.emit("authorize", token),如果您使用此方法,则在服务器端使用socket.on("authorize", (token) => do something with token ); 处理它,您需要确保未经授权的socket 不会从服务器接收任何数据/发射,也许您可​​以创建一个单独的sockets 数组并仅将授权的套接字存储在那里。 或者您可以在服务器端创建名为authentiated 的套接字空间,并且只发射到该房间内的套接字。更多关于房间here

以上是关于是否可以仅在用户登录时连接 Socket.io?的主要内容,如果未能解决你的问题,请参考以下文章

在重新连接、socket.io、node.js 时重用套接字 id

socket.io 在空闲时断开客户端的连接

是否可以将 Websockets/Socket.IO 与蜂窝数据/4g 一起使用?

无法获取 socket.io.js

在 socket.io 中与握手数据一起发送自定义数据?

Node.js Socket.io 设置多个连接