使用Express.js v4和Socket.io v1进行会话

如何在express.js中保存会话数据并在socket.io事件中访问它?

我正在使用express.js v4socket.io v1和基本的快速会话中间件来开发web应用程序。

我花了几个小时试图解决这个问题,但堆栈溢出的所有当前答案只适用于expressionv3和socket.io v0.9。 不幸的是,我不能使用express.io,因为它只是一个使用这些旧版本的包装器。

我目前的解决scheme是彻底的黑客攻击

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... } }); }); 

我将基于会话ID的“会话数据”保存在对象中作为键/值存储区。 这对于单个进程应用程序来说工作得很好,但它确实不是一个好的解决scheme。 它实际上并没有给我访问保存在req.session中的任何东西,如果过程结束,我保存的所有数据都将丢失。

最重要的是,我需要加载第三方的cookie包来parsing来自socket.io的cookiestring。 似乎新版本的Cookieparsing器没有使用它的函数来parsingstring中的cookie。 至less,没有logging。

有一个更好的方法!

编辑:最后,我决定使用Express Redis,并在socket.io中写了一个函数,根据会话ID从redis获取信息。

您可以将会话存储在Memcached或Redis中。 然后,您可以从任一商店获取会话数据。

memcache和redis包都可用于nodejs。

另请注意,您可以在socket.io中使用中间件进行身份validation。 然后,您不必将身份validation逻辑放入连接事件处理程序中。

 var authorization = require('./socket/authorization')(app); io.use(authorization.authorize); 

作为例子,这个memcachedauthentication的东西,在我们的情况下,阅读我们的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 }; }; 

我有一个类似的问题使用express.js 4.0和socket.io 0.9。 为了解决这个问题,我使用自己的function设置了“授权”过程,这是对我在网上find的一些解决scheme的修改。 在这个函数中,您将会话添加到数据属性并从套接字的handshake属性中访问它。 看看代码。

我创build了这个内容的套接字文件夹中的index.js:

 sio.set('authorization', function(data, accept){ /* NOTE: To detect which session this socket is associated with, * we need to parse the cookies. */ if (!data.headers.cookie) { return accept(null, true); } data.cookie = cookie.parse(data.headers.cookie); data.cookie = parse.signedCookies(data.cookie, sessionContainer.secret); data.sessionID = data.cookie[sessionContainer.key]; sessionContainer.store.get(data.sessionID, function(err, session){ if (err) { return accept('Error in session store.', false); } else if (!session) { return accept('Session not found.', false); } if(!session.username){ return accept('Session not authenticated', true); } data.session = session; return accept(null, true); }); }); 

然后使用会话中存储的数据:

 sio.sockets.on('connection', function (socket) { var hs = socket.handshake; /* NOTE: At this point, you win. You can use hs.sessionID and * hs.session. */ if(hs.sessionID){ // logged in user console.log('A socket with sessionID '+hs.sessionID+' connected.'); // here you can access whatever you stored in the session console.log('User ' + hs.session.username); socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); clientSockets[hs.sessionID] = socket; // handle the disconnect socket.on('disconnect', function () { if(clientSockets[hs.sessionID]){ console.log('deleted unused socket ' + hs.sessionID); delete clientSockets[hs.sessionID]; } }); } }); 

你可以在下面的链接中find整个项目https://github.com/landreus/dimiblog/blob/master/sockets/index.js

希望能帮助到你!