Node.js 在Express应用程序中验证Socket.IO客户端
我已经启动并运行了一个Express应用程序,它使用Passport.js(使用MongoDB后端)进行身份验证 一切都很顺利,但现在我面临另一个挑战: 我希望在我的项目中有某种“聊天”功能,为此我使用Socket.IO(实时传递消息) 该页面验证用户在加载之前是否已登录,但仍然可以绕过该页面 我希望Socket.IO流也得到保护和授权Node.js 在Express应用程序中验证Socket.IO客户端,node.js,authentication,socket.io,passport.js,Node.js,Authentication,Socket.io,Passport.js,我已经启动并运行了一个Express应用程序,它使用Passport.js(使用MongoDB后端)进行身份验证 一切都很顺利,但现在我面临另一个挑战: 我希望在我的项目中有某种“聊天”功能,为此我使用Socket.IO(实时传递消息) 该页面验证用户在加载之前是否已登录,但仍然可以绕过该页面 我希望Socket.IO流也得到保护和授权 如何将Socket.IO聊天系统集成到基于Passport.js的身份验证中?我不确定Passport是如何工作的,但假设它在客户端上使用会话id设置cooki
如何将Socket.IO聊天系统集成到基于Passport.js的身份验证中?我不确定Passport是如何工作的,但假设它在客户端上使用会话id设置cookie,那么以下解决方案应该可以工作。这似乎有点骇人,但我还没有看到一个更优雅的解决方案
var connect = require('express/node_modules/connect'),
parseSignedCookie = connect.utils.parseSignedCookie,
Cookie = require('express/node_modules/cookie'),
store = YOUR_SESSION_STORE_INSTANCE, // i.e. redis-store, memory, or whatever
sessionKey = "YOUR SESSION KEY", // defaults to connect.sid
sessionSecret = "YOUR SESSION SECRET";
var verifyCookie = function(data, callback){
try{
var cookie = Cookie.parse(data.headers.cookie);
var sessionID = parseSignedCookie(cookie[sessionKey], sessionSecret);
store.get(sessionID, callback);
}catch(e){
callback(e);
}
};
// set up socket.io to validate cookies on an authorization request
// this assumes you've assigned your socket.io server to the io variable
io.configure(function(){
io.set("authorization", function(handshake, accept){
if(handshake.headers.cookie){
verifyCookie(handshake, function(error, session){
if(error || !session)
accept("Invalid authentication", false);
else
accept(null, true);
});
}else{
accept("Invalid authentication", false);
}
});
});
我这里不是100%确定,但是如果这不能正确地拾取会话,您可能必须将上面使用的会话存储更改为passport的会话存储,而不是默认的express存储或您正在使用的任何存储
希望有帮助。如果这是可行的,或者如果你找到了正确的解决方案,请发布你的发现,因为我们将来可能也会使用passport,知道如何修补我们现有的代码会很好
编辑:在进行更多的探索之后,看起来在您从cookie中获取会话数据(如上所示)之后,您必须找到用户id属性并将该数据传递给passport。他们在上展示的示例是:
编辑2:另一个选择是完全回避这个问题。在实现上面列出的解决方案之前,我们走了一条不同的路线,涉及存储在redis中的一次性令牌。在高层次上,流程是这样工作的:
这种方法还使WS-authentication机制独立于WS-library。出于安全原因,Sockjs不提供连接请求时对cookie的访问,因此这种方法使我们从socket.io切换到Sockjs更容易。如果您正在开发基于Express 4.x版和socket.io 1.x版的应用程序,您可能需要阅读本文: 在我的例子中,验证过程的代码如下所示:
io.use(function(socket, next) {
var handshake = socket.handshake;
if (handshake.headers.cookie) {
var req = {
headers: {
cookie: handshake.headers.cookie,
}
}
cookieParser(config.session.secret)(req, null, function(err) {
if (err) {
return next(err);
}
var sessionID = req.signedCookies[config.session.name] ||
req.cookies[config.session.name];
var sessionStore = new MongoStore({ db: global.db});
sessionStore.get(sessionID, function (err, session) {
if (err) {
return next(err);
}
// userData bellow is written once the Express session is created
if (session && session.userData) {
next();
} else {
return next(new Error('Invalid Session'));
}
})
});
} else {
next(new Error('Missing Cookies'));
}
});
io.use(function(socket, next) {
var handshake = socket.handshake;
if (handshake.headers.cookie) {
var req = {
headers: {
cookie: handshake.headers.cookie,
}
}
cookieParser(config.session.secret)(req, null, function(err) {
if (err) {
return next(err);
}
var sessionID = req.signedCookies[config.session.name] ||
req.cookies[config.session.name];
var sessionStore = new MongoStore({ db: global.db});
sessionStore.get(sessionID, function (err, session) {
if (err) {
return next(err);
}
// userData bellow is written once the Express session is created
if (session && session.userData) {
next();
} else {
return next(new Error('Invalid Session'));
}
})
});
} else {
next(new Error('Missing Cookies'));
}
});