【问题标题】:Socket.IO and Express session not sharing their sessionSocket.IO 和 Express 会话不共享它们的会话
【发布时间】:2021-05-21 16:33:09
【问题描述】:

我正在尝试连接 express API 和 socket.IO 服务器的会话。但似乎两者都分别存储他们的会话。 socket.IO 有连接会话,而 express 服务器有用户 qid 会话。我正在使用 express ^4.17.1 和 socket.IO ^4.1.2。这是我的代码:

/server.js

const express = require("express");
const session = require("express-session");
const sharedSession = require("express-socket.io-session");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser("secret"));
const corsConfig = {
  origin: function (origin, callback) {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
  credentials: true,
};

const server = require("http").createServer(app);
const io = require("socket.io")(server, { cors: corsConfig });

const whitelist = ["http://localhost:3000", "http://192.168.2.104:3000"];

const sessionMiddleware = session({
  secret: "keyboard cat",
  cookie: { maxAge: 60000 },
  name: "qid",
});
// register middleware in Express
app.use(sessionMiddleware);
// register middleware in Socket.IO
io.use((socket, next) => {
  sessionMiddleware(socket.request, {}, next);
  // sessionMiddleware(socket.request, socket.request.res, next); will not work with websocket-only
  // connections, as 'socket.request.res' will be undefined in that case
});

// TRIED, BUT SAME RESULT. . .
// io.use(sharedSession(sessionMiddleware, { autoSave: true }));

app.get("/", (req, res) => {
  req.session.qid = "sdfdsfsadgfas";
  req.session.save();
  console.log(
    "CONNECTIONS / QID (EXPRESS SERVER)",
    req.session.connections,
    req.session.qid
  );
  res.json({ success: true });
});

io.on("connection", (socket) => {
  const session = socket.request.session;
  // console.log(socket.request);
  if (!session.connections) session.connections = 0;
  session.connections++;
  session.save();
  socket.on("a", () => {
    session.reload((err) => {
      if (err) console.log("ERROR", err);

      console.log(
        "CONNECTIONS / QID (IO SERVER)",
        session.connections,
        session.qid
      );
    });
  });
});

const port = process.env.PORT || 5000;
server.listen(port, () => console.log("server listening on port " + port));

/client.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Test</title>
  </head>
  <body></body>
  <script
    src="https://cdn.socket.io/3.1.3/socket.io.min.js"
    integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh"
    crossorigin="anonymous"
  ></script>
  <script>
    const socket = io("http://localhost:5000");
    fetch("http://localhost:5000/").then(() => socket.emit("a"));
  </script>
</html>

请帮我解决这个问题。 提前致谢。

【问题讨论】:

  • 应该是——express是web服务器,socket.io是websocket服务器;他们的会话非常不同,express 仅充当设置 websocket 连接的传递中介。作为 Web 服务器,express 接收到带有“请将此连接升级到 websocket 连接”指令的 HTTP GET 请求,它通过将其交给 socket.io 而不是自己做任何事情来兑现。之后 express 完成:它永远不会参与任何 websocket 通信,并且不应该知道任何关于 socket 会话的事情。
  • 我明白了,你知道合并会话吗?
  • 为什么需要?您要解决什么问题需要他们都可以访问相同的会话数据? (因为这几乎肯定没有必要)。
  • 这不是会话信息,而是“用户信息”,所以我强烈建议编写一个用户类来保存这样的信息。用户登录到您的 Web 服务器,您创建他们的用户对象,他们的浏览器请求 websocket 连接,您的 Web 服务器请求 socket.io 接管,您让您的代码向它构建的套接字添加一个 user 属性,指向到那个用户对象。
  • 再次:网络服务器是任何连接建立的中介,因此网络服务器决定某人是否已正确验证。如果没有,则不允许 Web 套接字连接。如果他们有,你有。 websocket 没有理由知道有关 web 服务器会话管理的任何信息。

标签: javascript node.js express socket.io express-session


【解决方案1】:

你可以在连接的时候把加密的session id传到前面,然后在后端解密...

正面

const socket = io("http://localhost:5000?session=sessionIdEncrypted");

后端

io.on("connection", socket => {
    const givenSessionId = socket.handshake.query.session
    // here you decrypt the session id and find it in the store
})

【讨论】:

  • 我正在使用 httpOnly Cookie。如何从我的代码中访问它?
  • 您可以先调用后端并询问会话ID,然后将socket.io与检索到的会话ID连接...
  • 听起来不错,但是如果用户可以获取会话ID,httpOnly 属性的用途会不会丢失?调用 API 而不是直接访问 cookie。我将 sessionId 存储在 httpOnly cookie 中。对不起,我是初学者,如果我的观点不正确,请告诉我。
  • 这里没有关于 cookie 的问题,你提供加密的会话 id,并通过它的 id 检索会话......你有会话 id,所以你可以像文档说的那样做 @987654321 @,您在连接处获得会话,因此一旦检索到,您可以在每个套接字'on message'传递它
  • 非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
  • 2014-10-21
  • 2015-03-26
  • 2012-05-15
  • 2017-08-23
  • 2018-05-30
  • 2014-06-23
相关资源
最近更新 更多