在Express中更新cookie会话不会向浏览器注册

我已经build立了一个工作logintesting,如下所示:

var express = require('express'); var fs = require('fs'); var http = require('http'); var path = require('path'); var routes = require('./routes/index.coffee'); var passport = require('passport'); var LocalStrategy = require('passport-local').Strategy; var User = require('./userdb.coffee'); var app = express(); var RedisStore = require('connect-redis')(express); passport.use(new LocalStrategy(function(username, password, done) { return User.findOne({ username: username }, function(err, user) { if (err) { return done(null, false, message: error); } if (!user) { return done(null, false, { message: 'Unknown user' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Invalid password' }); } else { return done(null, user); } }); })); passport.serializeUser(function(user, done) { return done(null, user); }); passport.deserializeUser(function(user, done) { return done(null, user); }); app.configure(function() { app.set('port', process.env.PORT || 5003); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.enable('trust proxy'); app.use(express["static"](path.join(__dirname, 'public'))); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser('SOMESECRET')); app.use(express.session({ cookie: { maxAge: 10 * 60 * 1000 }, key: 'express.sid', secret: 'SOMESECRET', store: new RedisStore({ port: 6379, host: 'localhost' }) })); app.use(passport.initialize()); app.use(passport.session()); return app.use(app.router); }); var check_auth = function(req, res, next) { if (req.isAuthenticated()) { console.log(req.session.cookie.expires); return next(); } return res.redirect('/login'); }; app.get('/', check_auth, routes.index); app.get('/login', routes.login); app.get('/logout', routes.logout); app.post('/authenticate', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' })); app.listen(app.get('port'), '0.0.0.0'); 

路由和用户逻辑被省略,因为我认为它们与我的问题无关,但如果需要,我会很乐意分享它们(它们非常小,这只是为了得到一个小的概念certificate,并运行) 。

login工作,阅读会议的作品,基于会话值的渲染模板工作。 我的问题是maxAge / expires 。 我不确定问题在哪里,但是我会试着去描述它:

当我login时,会话将保存在passport.js ,正确存储在我的RedisStore ,指向会话的cookie将返回给浏览器。 在随后的请求中,cookie被成功find,并从我的SessionStore指向正确的会话。 req.session.cookie显示更新expires并在我的redis服务器中,TTL重置为10分钟(600)。

我的问题是,cookie仍然在浏览器(铬,Windows和Mac)相同的expirary。

所以我的问题是 :我怎样才能进一步debugging呢? 当req.session被更新(通过expresspassportconnect-redis内部/自动),我想知道问题出在哪里,我该怎么做才能解决这个问题: Cookie保持在最初的maxAges / expires

任何提示,指针或想法感激不尽。

Express会话支持滚动cookie过期date。 不幸的是,这只是最近logging。

在会议中使用“滚动”选项。 这“强制设置每个响应的cookie”和“重置到期date”。 你想将滚动设置为true。

另外要注意“重新保存”选项。 即使在未修改的情况下也会强制保存会话…“您可能也希望将该选项设置为true。 请注意,即使此选项的默认值为true,也应该明确设置该值。 依靠此选项的默认值,而不是显式设置,现在已被弃用。

尝试像这样:

 app.use( session( { secret: 'keyboard cat', cookie: { maxAge: 60000 }, rolling: true, resave: true, saveUninitialized: false } ) ); 

这里是文档。 查看“选项”和“options.resave”: https : //github.com/expressjs/session 。

经过一番挖掘后发现,Express并不支持这种滚动方式,只能作为程序员实现的练习。

如果浏览器的expirary可以被可读地express ,那么它会有所帮助,所以只有当它接近expirary的时候才会使会话崩溃,但是我把它用作解决方法(效率低下),直到我找出更聪明的东西:

 check_auth = function(req, res, next) { console.log(req.isAuthenticated()); if (req.isAuthenticated()) { if (req.session.roll) { req.session.roll = 0; } else { req.session.roll = 1; } return next(); } return res.redirect('/login'); }; 

哪里roll可以是任何东西,会话的点是改变的(每个auth-checked请求*)。

*)这也意味着它是非常低效的,但它现在会做。

一种替代方法是查找会话ID的TTL。 这将不得不以如下方式进行检查:如果ttl <10%* maxAge(由应用程序定义),因为TTL实际上是在每个请求上正确更新的,只是没有发送Set-Cookie。 因此,如果用户停留在maxAge的90%以内,他的浏览器cookie将最终过期,所以即使这种方法也是不够的。 不过这可能是一个很好的中间环境。

我将不接受这个问题,鼓励他人用更好的解决scheme来衡量。

Interesting Posts