[英]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.