如何将 session 数据保存在express.js中并可以在socket.io事件中对其进行访问?
我正在使用 express.js v4 , socket.io v1 和基本express-session中间件开发一个Webapp。
我花了几个小时试图解决这个问题,但是有关Stack Overflow的所有当前答案仅适用于Express v3和socket.io v0.9。不幸的是,我不能使用express.io,因为它也只是使用那些旧版本的包装器。
我当前的解决方案是完全破解:
app.get('/auth', function(req, res) {
if(verified(req.query)) {
authed[req.sessionID] = true;
}
});
io.sockets.on('connection', function(websocket) {
var cookies = cookie.parse(websocket.handshake.headers.cookie);
var decrypted = cookieParser.signedCookies(cookies, random);
var sessionID = decrypted['connect.sid'];
websocket.on('input', function(input) {
if(authed[sessionID]) {
// Do stuff...
}
});
});
我正在根据 session ID将“ session 数据”保存在对象中作为键/值存储。这对于单流程应用程序工作正常,但实际上不是一个好的解决方案。它实际上并没有使我能够访问req.session中保存的任何内容,如果该过程结束,则所有保存的数据都将丢失。
最重要的是,我需要加载第三方cookie包来解析来自socket.io的cookie字符串。似乎新版本的cookie-parser取消了其从字符串中解析cookie的功能。至少没有记录。
一定有更好的方法!
编辑:最后,我决定使用express redis,并在socket.io中编写了一个函数,以基于 session ID从redis获取信息。
最佳答案
您可以将 session 存储在Memcached或Redis中。然后,您可以从任何一个存储中获取 session 数据。
memcache和redis软件包均可用于nodejs。
还要注意,您可以在socket.io中使用中间件进行身份验证。然后,您不必将身份验证逻辑放入连接事件处理程序中。
var authorization = require('./socket/authorization')(app);
io.use(authorization.authorize);
作为示例,此memcached auth内容在我们的情况下是读取由我们的php存储的cookie。
var memcached = require('memcached'),
cookie = require('cookie),
debug = require('debug')('socket.io:authorization');
module.exports = function(app) {
var authorize = function(socket, next) {
var handshakeData = socket.request;
if (handshakeData.headers.cookie) {
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
if (typeof handshakeData.cookie['node'] === 'undefined') {
next(new Error('No cookie transmitted.'));
} else {
var loginEndIndex = handshakeData.cookie['node'].indexOf(',');
handshakeData.node = handshakeData.cookie['node'].slice(0, loginEndIndex);
var memcached = new Memcached(app.config.memcached.server, app.config.memcached.options);
memcached.on('failure', function(details) {
debug('Server: %s went down due to %s', details.server, details.messages.join(' '));
});
memcached.on('reconnecting', function(details) {
debug('Total downtime caused by server %s: %sms', details.server, details.totalDownTime);
});
memcached.get(handshakeData.cookie['PHPSESSID'], function(err, result) {
if (!err && result !== false) {
var pipeIndex = result.indexOf('|'),
phpData = result.slice(pipeIndex + 1),
obj = php.unserialize(phpData);
if (handshakeData.node === obj.userLogin) {
debug('coockie-accepted: %s, %s', handshakeData.node, obj.userLogin);
next();
} else {
debug('cookie-revoked; %s, %s', handshakeData.node, obj.userLogin);
next(new Error('Cookie is invalid.'));
}
} else {
debug('error: %s', err);
next(new Error('Cookie is invalid.'));
}
memcached.end();
});
}
} else {
debug('error: No cookie transmitted.');
next(new Error('No cookie transmitted.'));
}
};
return {
authorize: authorize
};
};