簡體   English   中英

Passport和Socket.IO-是否保持使用Socket.IO登錄?

[英]Passport and Socket.IO - Keep logged in with Socket.IO?

我正在使用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);

我想通了。 我刪除了會話的TTL / maxAge。 當然,我想確保斷開連接時該會話被銷毀,但刷新后不斷開。 我的其他問題是,即使使用ping / pong方案,客戶端也會斷開約310秒的空閑時間。 此后,我刪除了ping / poning並更新了客戶端以在斷開連接時重新連接,並更新了斷開連接代碼以確定它是刷新/臨時斷開連接還是完全斷開連接。 這是一些簡化的代碼:

斷絕:

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();
});

我希望這可以幫助其他人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM