当用户注销 Express、Socket.io、PassportJS 时设置新的会话 ID

Set new session ID when user logs out Express, Socket.io, PassportJS

我正在编写一个消息传递应用程序,我正在使用 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);
        });
    }
    ));
}

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

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