【问题标题】:How to get persistent express session id in socket.io connection?如何在 socket.io 连接中获取持久的快速会话 ID?
【发布时间】:2019-08-30 12:06:50
【问题描述】:

我正在构建一个 MEAN 堆栈聊天应用程序。我希望能够在连接处理程序上的 socket.io 中获取快速会话 ID。我可以访问 socket.handshake.session.id 但它与 req.session.id 不同。进一步的 socket.handshake.session.id 在每个套接字上不断变化。

我已尝试通过查找 connect.sid 键从 req.handshake.cookie 获取会话 ID 来解决此问题,但该键未在其中定义。

const cors = require('cors'),
express = require('express'),
eSession = require('express-session'),
cookieParser = require('cookie-parser'),
MongoStore = require('connect-mongo')(eSession),
sharedsession = require('express-socket.io-session'),
http = require('http'),
bodyParser = require('body-parser'),
socketio = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketio(server);

const port = process.env.PORT || 3000;
//imports
const mongoose = require('./config/dbconnection');

//routes
const user = require('./api/routes/user');

const socketHandle = (io, mStore) => {
   io.on('connection', (socket) => {
     socket.on('join', (options, callback) => {

     console.log(socket.handshake.headers.cookie); //no connect.sid string present
     console.log(socket.handshake.session.id) // has value but keeps changing on each io connection and this id is not the same as req.session.id in an api endpoint method

    });
  }); 

const corsOptions = {
  origin: 'http://localhost:4200',
  optionsSuccessStatus: 200
};

const db = mongoose.connection;
const mStore = new MongoStore({ mongooseConnection: db });
const session = eSession({
  secret: 'my-secret',
  resave: true,
  saveUninitialized: true,
  store: mStore
});

app.use(cookieParser('my-secret'));
app.use(session);
io.use(sharedsession(session,{autoSave:true}));

socketHandle(io, mStore);

//body-parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(cors(corsOptions));

app.use('/user', user);

server.listen(port, () => console.log(`listening on http://localhost:${port}`));

socket.handshake.session.id 和 socket.handshake.headers.cookie(connect.sid key) 都应该提供与 req.session.id 具有相同值的会话 id

【问题讨论】:

  • 我在这里遇到了完全相同的问题

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


【解决方案1】:

@Anand Kashyap 是正确的,如果您让 express 服务器为您的客户端服务,cookie 将会存在。

但是,当您的客户端在不同的主机上时,您需要将 withCredentials: true 传递给套接字的构造函数。这会将 cookie 附加到请求中,并且会话将起作用。

const io = require("socket.io-client");

const socket = io("ws://example.com/", {
  withCredentials: true,
  autoConnect: 10000
});

【讨论】:

    【解决方案2】:

    我试过了,你的代码对我有用,所以我认为你的会话存储有问题。似乎您的 socket.handshake.session 和您的 express-session 之间没有交互,可能是因为您没有将其正确存储在 mongo 中。试试这个,然后围绕它构建你的应用程序:)

    const express = require('express');
    const eSession = require('express-session');
    const MongoStore = require('connect-mongo')(eSession);
    const mongoose = require('mongoose');
    const sharedsession = require('express-socket.io-session');
    const http = require('http');
    const socketio = require('socket.io');
    
    const app = express();
    const server = http.createServer(app);
    const io = socketio(server);
    
    const port = process.env.PORT || 3000;
    
    const socketHandle = (io) => {
       io.on('connection', (socket) => {
         console.log(socket.handshake.session.id) // same value on every connection
      }); 
    }
    
    // Connect with MongoDB (database called 'test')
    mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true, useCreateIndex: true })
        .then(() => console.log('Connected with MongoDB!'))
        .catch(err => console.log(err));
    
    let db = mongoose.connection;
    
    const mStore = new MongoStore({ mongooseConnection: db });
    const session = eSession({
      secret: 'my-secret',
      resave: true,
      saveUninitialized: true,
      store: mStore
    });
    
    app.use(session);
    io.use(sharedsession(session,{autoSave:true}));
    
    socketHandle(io);
    
    // Static folder
    app.use(express.static('public')); //Basic html page for socket connection
    
    server.listen(port, () => console.log(`listening on http://localhost:${port}`));
    

    现在,如果您查看会话集合,您将看到它已存储并且 id 与 handshake.session.id 相同。希望这对你有用:)

    【讨论】:

    • Djinii 是否有必要使用 app.use(express.static('public')) 来获得相同的套接字 id?我正在尝试通过 ng serve 在不同的端口上连接套接字。
    • 不,没有必要。我只是为了尝试一下。当您在另一个端口上侦听时,请确保您的端口是相同的。
    • @Djinii 我尝试了您的示例并且得到了不同的 session_ids,控制台日志:“KOyRyj5icAr3FUWpvoRSoEC3EhZueBZV”和 Mongo 中的“0nkOKn5HaUIWg6adm0SaOSRDoSMnh1wR” - 怎么会?我在这里拉头发……
    【解决方案3】:

    我的代码没有任何问题。导致不同会话 id 的唯一原因是我在与节点服务器不同的端口上运行角度。我不得不 ng build --watch for angular 并在节点服务器的静态文件文件夹中输出文件。通过这样做,我能够在路由和套接字 io 中获得一致的会话 ID。

    【讨论】:

    • 我在这里遇到了完全相同的问题: socket.handshake.session.id: "-armMd830gjfhLP7BRXXK3rLWeDDLlNu" socket.handshake.headers.cookie: "io=s_h5pcLB_9NSXUHLAAAA" 你似乎已经解决了,可以你解释你的答案多一点?我还使用构建文件获取静态信息,但没有运气。
    • @FabianBosler 您是否将前端文件保存在 expressjs 的静态目录中?
    • 朱普,我是。纱线构建并引用该文件夹。
    • Socket id 应该是一样的。至少在构建前端之后。你能分享你的快速做套接字连接和检查id的代码吗
    猜你喜欢
    • 2012-09-27
    • 2012-11-05
    • 2016-05-06
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 2018-09-03
    • 2022-11-27
    相关资源
    最近更新 更多