快速更新 cookie 会话未向浏览器注册
Posted
技术标签:
【中文标题】快速更新 cookie 会话未向浏览器注册【英文标题】:Updating cookie session in express not registering with browser 【发布时间】:2012-10-16 21:51:51 【问题描述】:我已经设置了一个有效的登录测试,如下所示:
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');
省略了路由和用户逻辑,因为我认为它们与我的问题无关,但如果需要,我会很乐意分享它们(它们非常小,这只是为了获得一个小的概念证明并运行)。
登录工作,阅读会话工作,基于会话值呈现模板工作。 我的问题是 maxAge/expires。我不确定问题出在哪里,但我会尝试描述一下:
当我登录时,会话以passport.js
保存,正确存储在我的RedisStore
中,并且指向会话的cookie 返回到浏览器。
在随后的请求中,cookie 被成功找到并从我的SessionStore
指向正确的会话。 req.session.cookie
显示更新后的expires
,在我的redis
服务器中,TTL 重置为 10 分钟 (600)。
我的问题是 cookie 在浏览器(Chrome、Windows 和 Mac)中保持相同的过期时间。
所以我的问题是:如何进一步调试?
随着 req.session 的更新(由express
、passport
和connect-redis
内部/自动更新),我想知道问题出在哪里,我应该怎么做才能解决这个问题:Cookie 仍处于初始状态maxAges/expires.
非常感谢任何提示、指示或想法。
【问题讨论】:
【参考方案1】:Express-session 支持滚动 cookie 到期日期。不幸的是,它只是最近才被记录下来。
为您的会话使用“滚动”选项。这“强制在每个响应上设置 cookie”并“重置过期日期”。您想将 rolling 设置为 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。
【讨论】:
查看代码,rolling
设置似乎并没有真正重置到期日期。它只是将更新的 cookie 发送到浏览器。但是,如果 maxAge
例如没有更改,那么即使您有活动,它仍然会过期。【参考方案2】:
经过一番挖掘,事实证明 Express 不支持这种滚动,留给程序员实施作为练习。
如果浏览器的过期时间对于express
是可靠可读的,这将有所帮助,因此您只能在会话接近过期时才可以触发会话,但我将此作为一种解决方法(效率低下),直到我想出更聪明的方法:
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
可以是任何东西,会话的关键点发生了变化(在每个经过身份验证检查的请求上*)。
*) 这也意味着它非常低效,但现在可以。
另一种方法是查找会话 ID 的 TTL。这必须以如下方式进行检查: 如果 ttl
我将不接受这个问题,以鼓励其他人提出更好的解决方案。
【讨论】:
我遇到了同样的问题。我想要的是每次用户重新加载页面(或执行 AJAX)时更新 cookie,这样只有当用户有一段时间没有访问网站时它才会过期(过期时间)。session.touch()
似乎只在服务器端工作,而不是在客户端更新 cookie...【参考方案3】:
万一有人在谷歌浏览器中遇到这个问题,解决方案很简单:
app.use(cors(
allowedHeaders: ['Content-Type','Authorization'],
origin: '.dev.loc', <- your domain here, but it requires to have a dot infront
methods:['GET','POST','PUT','DELETE'],
preflightContinue: true
));
【讨论】:
以上是关于快速更新 cookie 会话未向浏览器注册的主要内容,如果未能解决你的问题,请参考以下文章