【问题标题】:Node.js, ws and express-session : how to get session object from ws.upgradeReqNode.js、ws 和 express-session:如何从 ws.upgradeReq 获取会话对象
【发布时间】:2016-08-18 22:30:19
【问题描述】:

我有一个基于 express、express-session 和 ws 构建的应用程序(用于 websocket 支持)。

我已使用此代码启用会话中间件:

app.use(session({secret: 'mysecret',resave: true,saveUninitialized: true,cookie: {}}));

我可以在 get 处理程序中读取和保存会话变量:

app.get('/', function (req, res) {
  res.send('Hello World!');
  console.log(req.session.test);
  req.session.test="OK";
  req.session.save();
});

(第一次打印“未定义”,第二次按预期打印“OK”)

现在我在同一个应用程序中也有一个由 express 处理的 websocket 服务器,我想在 ws.on("connection",...)ws.on("message",...) 中获取 req.session 对象。

问题是没有对原始req 对象的引用,只是对upgradeReq 的引用,它是websocket 的连接处理程序的包装器。 检查此 upgradeReq 我可以在 ws.upgradeReq.headers.cookie 中找到包含会话 cookie 值的 connect.sid

wss.on('connection', function connection(ws) {
  var location = url.parse(ws.upgradeReq.url, true);
  console.log(ws.upgradeReq.headers.cookie);
  //....
});

在我的想法中,有可能以某种方式从中获得原始的req.session

我怎样才能做到这一点?

【问题讨论】:

    标签: node.js session express websocket express-session


    【解决方案1】:

    好的,我找到了一种研究 express-session 源代码的无证方法。

    首先你需要cookiecookie-parser 作为你的依赖。

    所以,导入模块

    var cookie = require('cookie');
    var cookieParser = require('cookie-parser')
    

    然后,诀窍是在 ws“连接”事件处理程序中解码签名的 cookie,即当有 websocket 握手时。 首先,您需要从 cookie 中解码作为会话 ID 的 connect.sid(仅当您使用 express-session 进行会话管理时)

    wss.on('connection', function connection(ws) {
        var cookies=cookie.parse(ws.upgradeReq.headers.cookie);
        var sid=cookieParser.signedCookie(cookies["connect.sid"],secret);
        ...
    

    请注意密码与您在 express-session 中为签名设置的密码相同(即在 app.use(session({secret: secret, resave: true, saveUninitialized: true, cookie: {},store:store})); 中) 此时你在 sid 中​​有 sessoinID,你想从 express-session 中获取 Session 对象,它是从存储中异步传递给你的(有很多,请阅读文档,目前我只用快速会话的 MemoryStore)。

    为了获得会话然后在上面的行之后使用此代码

    ...
    store.get(sid,function(err, ss){
            store.createSession(ws.upgradeReq,ss)
        });
    

    回调函数将直接从存储中为您提供会话对象 (ss),但它是单独的且没有方法(只是反序列化的 JSON)。因此,出于这个原因,我们再次使用我们将 upgradeReq 和 ss 对象传递给的 store.createSession,这样我就有了一个包含所有记录方法的会话对象(所以我也可以从 ws 回调中修改会话)。

    新的会话对象在:

    ws.upgradeReq.session
    

    请注意: session 对象在 store 异步返回 ss 对象之前不可用,因此最好完成 websocket 事件绑定(例如 on('message',...)inside 传递给 store.get 的回调。

    这是完整的代码:

    wss.on('connection', function connection(ws) {
        var location = url.parse(ws.upgradeReq.url, true);
        //get sessionID
        var cookies = cookie.parse(ws.upgradeReq.headers.cookie);
        var sid = cookieParser.signedCookie(cookies["connect.sid"], secret);
        //get the session object
        store.get(sid, function (err, ss) {
            //create the session object and append on upgradeReq
            store.createSession(ws.upgradeReq, ss)
            //setup websocket bindings
            ws.on('message', function incoming(message) {
                console.log('received: %s', message);
                //..........
            });
    
        });
    });
    

    所以,现在您可以同时使用 ws 和 express-session 来管理会话数据。

    希望对你有帮助!

    【讨论】:

    • 仅供参考,当与 Passport 一起使用时,这对我也有用。在这种情况下,我最终在 ws.upgradeReq.session.passport.user 中使用了 te 用户。谢谢!
    • 您好,我正在尝试做同样的事情,但我不明白为什么 ws.upgradeReq 未定义。有人可以帮帮我吗?
    • @dritan 最近 ws 3.0 发生了重大变化。 ws.upgradeReq 已被删除。搜索“ws Breaking change upgradeReq”可以获得更多信息。
    【解决方案2】:

    我刚刚发现在 3.0.0 版本中 upgradeReq 已从 WebSocket 中删除。 alexroat 现有代码的解决方法:

    wss.on('connection', function connection(ws, req) {
        ws.upgradeReq = req;
        var location = url.parse(ws.upgradeReq.url, true);
        //get sessionID
        var cookies = cookie.parse(ws.upgradeReq.headers.cookie);
        var sid = cookieParser.signedCookie(cookies["connect.sid"], secret);
        //get the session object
        store.get(sid, function (err, ss) {
            //create the session object and append on upgradeReq
            store.createSession(ws.upgradeReq, ss)
            //setup websocket bindings
            ws.on('message', function incoming(message) {
                console.log('received: %s', message);
                //..........
            });
        });
    });
    

    【讨论】:

    • 男人!!你刚刚救了一条命。
    猜你喜欢
    • 2020-10-13
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2015-04-14
    • 2017-10-28
    相关资源
    最近更新 更多