【问题标题】:How do I keep a socket io ID while using changing html files?如何在使用更改 html 文件时保留套接字 io ID?
【发布时间】:2025-12-24 00:35:12
【问题描述】:

我正在使用 express 和 node 来托管服务器。我也有socket io,我试图通过保存他们的socket.id来跟踪用户。但是,我有两个 webapp 页面,一个用于登录,一个用于实际内容。

app.get("/", function(req, res) {
    res.sendFile(__dirname + "/login.html")
})

app.get("/content", function(req, res){
    res.sendFile(__dirname + "/index.html");
})

在我的 login.html 中,我必须让用户登录,然后单击一个按钮,我将 window.location.href 设置为链接到 index.html。由于客户端socket io是在login.html和index.html中创建的;从登录名更改为索引会刷新实例,为用户提供一个新的 socket.id。我将如何解决这个问题并将访问 login.html 然后重定向到 index.html 的用户作为同一用户链接?

【问题讨论】:

    标签: html node.js express socket.io


    【解决方案1】:

    你应该使用 session 来保存 socket id,不要将 id 保存到客户端

    查看更多:https://www.npmjs.com/package/express-socket.io-session

    【讨论】:

      【解决方案2】:

      我建议在客户端成功登录后向客户端发送访问令牌,然后他们可以将其存储在 localStorage 或 cookie 中;在页面加载之间持续存在的地方。

      然后当他们加载任何其他页面时,您发送令牌以验证 websocket 连接。除了识别用户之外,这还有一个额外的优势,即允许您保护 websocket 连接。

      这里有一个简短的例子

      /// Server
      
      var users = {
        'asdf123': { id: 'asdf123', name: 'jack', userConnections: [] }, // user could have multiple pages open, track all sockets
        '123asdf': { id: '123asdf', name: 'jill', userConnections: [] },
      };
      
      function onLogin(req, res) {
        // do some database login
        var user = users[asdf123];
        var token = jsonwebtoken.sign({ userId: user.userId }, 'secret signing key');
        res.json({ token: token });
      }
      
      io.on('connection', function (socket) {
        socket.authenticated = false; // have they sent us a valid token yet
        socket.on('auth', function (token) { // client will explicitly send the token
          jsonwebtoken.verifyToken(token, function (err, decodedToken) {
            if (err) { // bad or expired token, disconnect them.
              socket.disconnect();
              return;
            }
            if (users[decodedToken.userId]) {
              users[decodedToken.userId].userConnections.push(socket);
              socket.authenticated = true;
            }
          });
        });
      });
      
      /// Client
      
      var socket = io();
      var savedToken = localStorage.getItem('token');
      
      socket.on('connect', function () {
        socket.emit('auth', savedToken);
      });
      

      【讨论】:

      • 您还可以将套接字 ID 存储在 JWT 有效负载中。
      • 不可以,因为每个连接的socket id都是唯一的,所以当你加载不同的页面并打开一个新的websocket时会有所不同
      【解决方案3】:

      这基本上是不可能的,正如这个 * 帖子中所解释的那样:

      how to handle page reload in socket.io client chat applications

      但是,如上述答案所述,您可以:

      • 在 index.html 文件中移动 socketio 连接脚本
      • 在服务器端处理断开连接事件(注销/删除用户),以便在 index.html 页面重新加载时自然地重新注册
      • 在本地/会话存储中存储一些您保存在数据库中以与您的用户相关的 ID。

      【讨论】: