就在一个半月前,我处理了同样的问题,然后就这个主题写了一个广泛的blog post,与托管在 GitHub 上的完整工作的demo app 一起。该解决方案依赖于express-session、cookie-parser 和connect-redis 节点模块来绑定所有内容。它允许您从 REST 和 Sockets 上下文访问和修改会话,这非常有用。
两个关键部分是中间件设置:
app.use(cookieParser(config.sessionSecret));
app.use(session({
store: redisStore,
key: config.sessionCookieKey,
secret: config.sessionSecret,
resave: true,
saveUninitialized: true
}));
...和 SocketIO 服务器设置:
ioServer.use(function (socket, next) {
var parseCookie = cookieParser(config.sessionSecret);
var handshake = socket.request;
parseCookie(handshake, null, function (err, data) {
sessionService.get(handshake, function (err, session) {
if (err)
next(new Error(err.message));
if (!session)
next(new Error("Not authorized"));
handshake.session = session;
next();
});
});
});
它们与我制作的一个简单的 sessionService 模块一起使用,它允许您对会话进行一些基本操作,代码如下所示:
var config = require('../config');
var redisClient = null;
var redisStore = null;
var self = module.exports = {
initializeRedis: function (client, store) {
redisClient = client;
redisStore = store;
},
getSessionId: function (handshake) {
return handshake.signedCookies[config.sessionCookieKey];
},
get: function (handshake, callback) {
var sessionId = self.getSessionId(handshake);
self.getSessionBySessionID(sessionId, function (err, session) {
if (err) callback(err);
if (callback != undefined)
callback(null, session);
});
},
getSessionBySessionID: function (sessionId, callback) {
redisStore.load(sessionId, function (err, session) {
if (err) callback(err);
if (callback != undefined)
callback(null, session);
});
},
getUserName: function (handshake, callback) {
self.get(handshake, function (err, session) {
if (err) callback(err);
if (session)
callback(null, session.userName);
else
callback(null);
});
},
updateSession: function (session, callback) {
try {
session.reload(function () {
session.touch().save();
callback(null, session);
});
}
catch (err) {
callback(err);
}
},
setSessionProperty: function (session, propertyName, propertyValue, callback) {
session[propertyName] = propertyValue;
self.updateSession(session, callback);
}
};
由于整个事情的代码比这更多(比如初始化模块,在客户端和服务器端处理套接字和 REST 调用),我不会在这里粘贴所有代码,你可以查看它在 GitHub 上,你可以用它做任何你想做的事情。