【问题标题】:Set new session ID when user logs out Express, Socket.io, PassportJS当用户退出 Express、Socket.io、PassportJS 时设置新的会话 ID
【发布时间】:2016-04-06 08:35:45
【问题描述】:

我正在编写一个消息传递应用程序,我正在使用 Express、Socket.io、PassportJS。

目前,当用户连接时,他们会获得一个会话 ID。这与 websocket 共享。当通过 websocket 进行通信时,我使用socket.request.session 获取有关会话的 PassportJS 信息。从那里我反序列化用户,然后确保他们有权执行他们正在尝试的操作。

当用户注销时,如果他们尝试发送消息,我的应用程序会崩溃,因为即使我在服务器端销毁了 websocket,它仍然具有以前的会话 ID。

我不明白如何在用户注销时给他们一个新的会话 ID,以免他们最终导致服务器崩溃。

server.js:

var sessionStore = new MongoDBStore({
    uri: settings.dbUri,
    collection: settings.sessionCollection
});
var sessionMiddleware = session({
    secret: settings.sessionSecret,
    saveUninitialized: false,
    resave: false,
    cookie: {
        maxAge: 1000 * 60 * 60 * 24 * 7 // 1 week 
    },
    store: sessionStore
});
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());

io.use(function(socket, next) {
    sessionMiddleware(socket.request, {}, next);
});
io.use(function(socket, next) {
    passport.initialize();
    passport.session();
    next();
});
// Handle routing to applications
app.get('/', function(req, res) {
    res.sendFile('player.html', {root: __dirname + '/apps/player'});
});

function returnUserOrContinue (req, res, next) {
    console.log(req.isAuthenticated());
    if (req.isAuthenticated()) {
    var user = { user: {
        username: req.user.username
    }};
    res.json(user);
    } else {
    return next()
    }
}

// User API
app.post('/userApi/login',
     returnUserOrContinue,
     passport.authenticate('localSignUp'),
     function(req, res) {
         var user = { user: {
         username: req.user.username
         }};
         res.json(user);
     });

app.post('/userApi/logout', function(req, res) {
    if (req.isAuthenticated()) {
    req.session.destroy();
    }
    res.send(null);
});

function ifUserLoggedIn(sessionID, callback) {
    sessionStore.get(sessionID, function(err, session){
    if (session && session.passport.user) {
        passport.deserializeUser(session.passport.user, function(err, user) {
        callback(user);
        });
    }
    });
}
io.on('connection', function(socket) {
    console.log('new socket connection');

    // Admin land
    socket.emit('updateQueue');

    // User Land
    socket.on('syncVideo', function() {
    socket.emit('currentVideoChanged', videoQueue.getCurrentVideoInfo());
    });
    socket.on('sendMessage', function(messageInfo) {
    var sessionID = socket.request.sessionID;
    ifUserLoggedIn(sessionID, function(user) {
        socket.broadcast.emit('newMessage', messageInfo);
    });
    });
});

server.listen(listenPort, '0.0.0.0', function(){
    console.log('listening on *:', listenPort);
});

passport.js:

var LocalStrategy = require('passport-local').Strategy;
var userController = require('./models/user').controller;

module.exports = function(passport) {
    passport.serializeUser(function(user, callback) {
    callback(null, user.id);
    });
    passport.deserializeUser(function(id, callback) {
    userController.getUserById(id, callback);
    });
    passport.use('localSignUp', new LocalStrategy(
    function(username, password, next){
        userController.getUserByUsername(username, function(user) {
        if (!user) {
            var newUser = userController.addUser(username, password);
            return next(null, newUser);
        }
        if (!userController.validPassword(user, password)) {
            return next(null, null);
        }
        return next(null, user);
        });
    }
    ));
}

【问题讨论】:

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


    【解决方案1】:

    您可以在注销时调用 req.sesion.regenerate() 以生成具有新会话 ID 的新会话。

    req.session.regenerate(function(err) {
      // will have a new session here if no error
      res.send(null);
    });
    

    【讨论】:

    • 您可能想在 regenerate() 完成后做出响应,就像我在那里所做的那样。如果您在 regenerate 的回调之外调用 res.send(),用户可能没有新的 sessionId。
    • 对不起,我的评论不是要提交的:P。如何将此新 ID 传播到套接字连接?只是在客户端设置它当服务器响应?
    • 我不确定您是否可以在客户端设置 sessionID。我认为您可以在调用 res.send() 之前为该套接字设置会话 ID。以前没有做过,所以我不太确定。或者您可能必须让客户端使用新的 sessionId 重新连接套接字以同步 sessionId
    • 是的,手动重新连接客户端上的套接字为套接字提供了新的会话信息
    • 我的新会话正在创建,但会话 ID 未存储在 mongo 集合存储中,会话 ID 也未在浏览器中更新
    猜你喜欢
    • 2015-01-16
    • 1970-01-01
    • 2022-01-07
    • 2016-02-28
    • 2013-10-12
    • 2013-12-29
    • 2013-12-02
    • 1970-01-01
    • 2013-08-02
    相关资源
    最近更新 更多