9

我有一个基于 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 服务器,我想req.session在.ws.on("connection",...)ws.on("message",...)

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

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

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

我怎样才能做到这一点?

4

2 回答 2

10

好的,我找到了一种研究 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 中获取会话对象,即通过您从商店异步(有很多,请阅读文档,目前我仅使用 express-session 的 MemoryStore 进行了测试)。

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

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

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

新的会话对象可用于:

ws.upgradeReq.session

注意:在存储异步返回 ss 对象之前,会话对象不可用,因此完成 websocket 事件绑定是一个好习惯(就像on('message',...)在传递给 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 来管理会话数据。

我希望它会有所帮助!

于 2016-04-25T22:12:38.883 回答
7

我刚刚发现在 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);
            //..........
        });
    });
});
于 2017-06-17T12:34:26.187 回答