nodejs - express和socket.io之间的共享会话(使用护照进行身份验证)

时间:2017-06-27 19:33:25

标签: node.js session express socket.io passport.js

我目前正在使用node.js创建一个web应用程序。 当用户进入侧面时,会建立通过socket.io的连接。 我想阻止多个连接。用户应该只能连接一次,如果他在另一个窗口中打开页面,我想显示一条消息,如“已经连接,请关闭所有其他标签”,或类似的东西。

为此,我使用“express-session”为用户创建会话。使用以下代码与socket.io共享此会话。 我不确定,如果我正确地做到了。我查看了一些教程,他们都以类似的方式分享会话。但有时,我认为,当我在socket.io-session中更改并保存一个值时会覆盖会话数据。

var sessionStoreClient = Redis.createClient({
    port: DBs.sessionStore_redis.port,
    host: DBs.sessionStore_redis.host,
    password: DBs.sessionStore_redis.password,
    db: DBs.sessionStore_redis.database
});
var sessionStore = new RedisStore({
    unset: "destroy",
    client: sessionStoreClient
});

var sessionInstance = expressSession(
    {
        key: sessionsKey,
        store: sessionStore,
        secret: sessionsSecret,
        unset: "destroy"
    }
);
app.use(sessionInstance);
app.use(passport.initialize());
app.use(passport.session());

与socket.io共享会话,我正在使用以下代码

var passportSocketIo = function(app,sessionInstance, passport){
return function(socket, next){

    var req = socket.request;

    sessionInstance(req,req.res,
        function () {

            if (!req.session) {
                return next(new Error("Not authorized"), false);
            }

            req.updateSessionValue = function (propertyName, propertyValue, callback) {
                if(!req.session){
                    console.log("unauthorized session modification");
                    return;
                }
                req.session.reload(()=>{
                    req.session[propertyName] = propertyValue;
                    req.session.save();
                    if(callback)
                        callback(propertyName, propertyValue,req.session);
                });
            };

            if(req.session.passport && req.session.passport.user) {
                passport.deserializeUser(req.session.passport.user, req, function (err, user) {
                    req.user = user;
                    req.user.logged_in = true;
                    return next(null, true);
                });
            }else {
                return next(null, true);
            }
        }
    );
    };
};

    var nsp = io.of(Packages.NAMESPACES.LOBBY);
    nsp .use(options.sessionMiddleware);

在socket.io-listeners内部编辑会话的值,我使用的函数在上面的代码中设置为请求。

_onConnectionReceived(socket) {
   socket.request.updateSessionValue("isConnected",true);
}

当用户从套接字断开连接时:

_onDisconnect(socket) {
   socket.request.updateSessionValue("isConnected",false);
}

对于登录和身份验证,我目前正在使用passport.js。

当用户退出时,他被重定向到同一页面,但被重定向到“guest”--user。对于loggin out,我使用以下代码:

router.get('/logout',function(req, res,next){
    req.logout();
    req.session.destroy(
        function (err) {
            res.render('logout',{});
        }
    );
});

问题是,在会话被销毁并且用户被重定向之后,会触发socket.io disconnect事件。即使在“onDisconnected”事件监听器内部重新加载之后,会话似乎仍然存在,在修改该值之后,会话似乎以某种方式重新创建。还有感觉,会话值有时只是被覆盖 - 我还没有找到原因。

任何人都可以解释我做错了什么,或者是否有更好的方式来分享和修改会话?会话的“重新加载”功能是否真的从sessionStore重新加载其数据?

另一种方法可能是将会话/用户ID保存在一个哈希集中,并检查是否已打开连接(不将其保存在自己的会话中),但我很好奇,如果我的方法是正确的,因为我无论如何都需要分享和修改会议。

0 个答案:

没有答案