Passport和Socket.IO - 继续使用Socket.IO登录?

时间:2016-02-04 17:09:53

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

我正在使用Express 4,Socket.IO 1.x以及最新的Passport。我可以登录,并且只要我在每次加载120秒内刷新我的屏幕(会话的生命时间),就可以保持登录状态。我有socket.io运行“ping / pong”,当服务器收到一个pong时,会话的到期时间更新,因此仍然有效。如果我在最后一次加载120秒后刷新屏幕,req.isAuthenticated()会返回false并将我踢出登录。如何让我自己使用socket.io登录?

这里有一些相关的代码:

var sessionMiddleware = session({
    store            : new RedisStore({}), // XXX redis server config
    secret           : 'Some Key!',
    cookie           : {maxAge: 120000},
    resave           : true,
    saveUninitialized: true
});

app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.urlencoded({extended: true}));
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static('public'));
app.use(flash());


io.use(function(socket, next)
{
    sessionMiddleware(socket.request, {}, next);
    //sessionMiddleware(socket.request, socket.request.res, next);
});

/**
 * Keeping the session alive through socket.io
 * Ping and Pong are reserved events on the client - so it's Ding and Dong for us!
 */
function sendHeartbeat()
{
    setTimeout(sendHeartbeat, 8000);
    io.emit('ding', {beat: 1});
}

app.get('/', function (req, res)
{
    console.log('--------');
    console.log('From Get');
    console.log(req.session);
    console.log('--------');
    if(!req.isAuthenticated())
    {
        res.redirect('/login');
        return;
    }

    res.render('index', {sessionid: req.sessionID});
});

passport.use(new LocalStrategy(function (username, password, done)
    {
        console.log(username);
        console.log(password);

        db.query('SELECT * FROM `agents` WHERE `username` = ?', [username], function (err, rows)
        {
            if(err)
            {
                console.log(err);
                return done(err);
            }
            var ret = JSON.parse(JSON.stringify(rows));

            if(ret.length != 1)
            {
                return done(null, false, {message: 'Incorrect username and/or password'});
            }

            if(!bcrypt.compareSync(password, ret[0].password))
            {
                return done(null, false, {message: 'Incorrect username and/or password'});
            }

            return done(null, ret[0]);
        });
    }
));

passport.serializeUser(function (user, done)
{
    done(null, user.agent_id);
});

passport.deserializeUser(function (agent_id, done)
{
    // Should use agent_id here - it's possibly faster.
    db.query('SELECT * FROM `agents` WHERE `agent_id` = ?', [agent_id], function (err, rows)
    {
        if(err)
        {
            console.log(err);
            return done(err);
        }
        var ret = JSON.parse(JSON.stringify(rows));
        console.log(ret[0]);
        done(null, ret[0]);
    });
});

app.get('/login', function (req, res)
{
    if(req.isAuthenticated())
    {
        res.redirect('/');
        return;
    }

    res.render('login');
});

app.post('/login', passport.authenticate('local', {
        successRedirect: '/',
        failureRedirect: '/login',
        failureFlash   : true
    })
);

io.on('connection', function (socket)
{
    console.log('--------');
    console.log('From IO');
    console.log(socket.request.session);
    console.log('--------');
    console.log('A socket with sessionID ' + socket.request.sessionID  + ' connected!');

    // Ping and Pong are reserved events on the client - so it's Ding and Dong for us!
     socket.on('dong', function (data)
     {
         // Keep session alive
         socket.request.session.touch().save(function(err)
         {
            if(err)
            {
               console.log('Could not touch and save the session');
               return;
            }

            console.log('GOT PONG');
         });
     });
});

setTimeout(sendHeartbeat, 8000);

1 个答案:

答案 0 :(得分:0)

我发现了。我删除了会话的TTL / maxAge。当然,我想确保会在发生断开连接时破坏会话,但不会在刷新后破坏。其他问题我是客户端会在大约310秒的空闲时间内断开连接,即使使用ping / pong方案也是如此。我已经删除ping / ponging并更新客户端以在断开连接时重新连接并更新断开连接代码以确定它是刷新/临时断开连接还是完全断开连接。这是一些简单的代码:

Sever的:

io.on('connection', function (socket)
{
    // Add the socket.id to our session.
    socket.request.session.socketid = socket.id;

    socket.request.session.save(function(err)
    {
        if(err)
        {
            console.log('ERR', err);
        }
    });

    socket.on('disconnect', function()
    {
        // Lets make sure that we do not kill off sessions for reloads or temp disconnect (network hickups)
        setTimeout(function()
        {
            socket.request.session.reload(function(err)
            {
                if(err)
                {
                    console.log('ERR: ', err);
                }

                if(socket.id == socket.request.session.socketid)
                {
                    // Full disconnect - destroy the session!
                    socket.request.session.destroy(function(err)
                    {
                        if(err)
                        {
                            console.log('Could not destroy the session', err);
                        }
                    });
                }
            });
        }, 5000);
    });
});

客户端:

socket.on('disconnect', function()
{
    // Reconnect after disconnect
    socket.socket.reconnect();
});

我希望这有助于其他人。