Node.js、ws 和 express-session:如何从 ws.upgradeReq 获取会话对象
Node.js, ws and express-session : how to get session object from ws.upgradeReq
我有一个基于 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();
});
(第一次打印 "undefined",第二次按预期打印 "OK")
现在我有一个 websocket 服务器,它也在同一个应用程序中由 express 处理,我想在 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
。
我怎样才能做到这一点?
好的,我在研究express-session的源代码中找到了一个未记录的方法。
首先你需要 cookie
和 cookie-parser
作为你的依赖。
所以,导入模块
var cookie = require('cookie');
var cookieParser = require('cookie-parser')
然后,诀窍是在有 websocket 握手时的 ws "connection" 事件处理程序中解码签名的 cookie。
首先,您需要从 cookie 中解码 connect.sid 即会话 ID(仅当您使用 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 中获取会话对象,它是从商店异步传递给你的(有很多,阅读文档,目前我只测试了MemoryStore of express-session).
为了获得会话,请在上面几行之后使用此代码
...
store.get(sid,function(err, ss){
store.createSession(ws.upgradeReq,ss)
});
回调函数将直接从存储中为您提供会话对象 (ss),但它是单独的且没有方法(只是反序列化的 JSON)。因此,出于这个原因,我们再次使用 store.createSession 我们将 upgradeReq 和 ss 对象传递给它,这样我就有了一个会话对象,它具有所有记录的方法(所以我也可以从 ws 回调修改会话) .
新会话对象可用于:
ws.upgradeReq.session
注意:
会话对象在异步存储 return 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 来管理会话数据。
希望对您有所帮助!
我刚刚发现 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);
//..........
});
});
});
我有一个基于 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();
});
(第一次打印 "undefined",第二次按预期打印 "OK")
现在我有一个 websocket 服务器,它也在同一个应用程序中由 express 处理,我想在 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
。
我怎样才能做到这一点?
好的,我在研究express-session的源代码中找到了一个未记录的方法。
首先你需要 cookie
和 cookie-parser
作为你的依赖。
所以,导入模块
var cookie = require('cookie');
var cookieParser = require('cookie-parser')
然后,诀窍是在有 websocket 握手时的 ws "connection" 事件处理程序中解码签名的 cookie。 首先,您需要从 cookie 中解码 connect.sid 即会话 ID(仅当您使用 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 中获取会话对象,它是从商店异步传递给你的(有很多,阅读文档,目前我只测试了MemoryStore of express-session).
为了获得会话,请在上面几行之后使用此代码
...
store.get(sid,function(err, ss){
store.createSession(ws.upgradeReq,ss)
});
回调函数将直接从存储中为您提供会话对象 (ss),但它是单独的且没有方法(只是反序列化的 JSON)。因此,出于这个原因,我们再次使用 store.createSession 我们将 upgradeReq 和 ss 对象传递给它,这样我就有了一个会话对象,它具有所有记录的方法(所以我也可以从 ws 回调修改会话) .
新会话对象可用于:
ws.upgradeReq.session
注意:
会话对象在异步存储 return 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 来管理会话数据。
希望对您有所帮助!
我刚刚发现 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);
//..........
});
});
});