Node.js Express Passport Cookie 过期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15016551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Node.js Express Passport Cookie Expiration
提问by creativename
I am using Passport for authentication in my app, and I am also using Express. To summarize my issue: my login functionality works fine initially, but after anyuser's session times out, nousers are able to log in.
我在我的应用程序中使用 Passport 进行身份验证,并且我也在使用 Express。总结我的问题:我的登录功能最初运行良好,但在任何用户的会话超时后,没有用户能够登录。
I am using the standard Local strategy for authentication.
我正在使用标准的本地策略进行身份验证。
I'll include as bare an example as possible based on my setup:
我将根据我的设置尽可能提供一个示例:
//-------------
//Set up authentication with Passport
//-------------
var userModel = require('./models/user')(db);
passport.use(new LocalStrategy(
function(username, password, done) {
var errorMessage = 'Incorrect username/password combination.';
userModel.GetUserByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: errorMessage });
}
user.validatePassword(password, function(isPasswordCorrect) {
if (!isPasswordCorrect)
{
return done(null, false, { message: errorMessage });
}
//Update with login date
userModel.UpdateUserWithLogin(username, user.currentLoginTime, function(err){
//if we have an error here, we should probably just log it
if(err)
{
console.log(err);
}
});
return done(null, user);
});
});
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
userModel.GetUserByUsername(user._id, function(err, user) {
done(err, user);
});
});
//-------------
//Set up express and configure
//-------------
var sessionStore = new SkinStore(db);
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.engine('html', consolidate.swig);
app.set('view engine', 'html');
swig.init({
root: '.',
allowErrors: true, // allows errors to be thrown and caught by express instead of suppressed
autoescape: false});
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser("[mysecrethere]"));
app.use(express.session({ store: sessionStore,
cookie: { expires : new Date(Date.now() + 3600000) } //1 Hour
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(expressValidator);
app.use(express.static(path.join(__dirname, 'public')));
//Dynamic helpers
app.use(require('./helpers/DynamicHelpers'));
app.use(app.router);
});
app.get('/login', routes.login);
app.post('/login', passport.authenticate('local', {failureRedirect: '/login',
badRequestMessage: "Please enter username and password",
failureFlash: true }),
function(req, res) {
var targetUrl = req.session.pageAfterLogin;
delete req.session.pageAfterLogin;
res.redirect(targetUrl || '/account');
});
app.get('/account', IsAuthenticated, routes.account.show);
And the IsAuthenticated helper function:
和 IsAuthenticated 辅助函数:
function IsAuthenticated(req,res,next){
if(req.isAuthenticated())
{
next();
}
else
{
//save the requested page and then redirected
req.session.pageAfterLogin = req.url;
req.flash("error", "You must be logged in first!");
res.redirect('/login');
}
}
What I can find by debugging is that, after successful authentication (and after a cookie has expired), I hit this logic (from above):
我可以通过调试发现,在成功认证后(以及 cookie 过期后),我遇到了这个逻辑(从上面):
function(req, res) {
var targetUrl = req.session.pageAfterLogin;
delete req.session.pageAfterLogin;
res.redirect(targetUrl || '/account');
}
Where I can see that the "req" has the session properly set, with Passport information stored properly. Then, the redirect happens, the newrequest has no session information stored, and has an entirely new Session ID. I suspected that no cookie was being set on the client, and that does appear to be the case, which should explain the lack of consistent sessions.
我可以看到“req”正确设置了会话,并正确存储了 Passport 信息。然后,重定向发生,新请求没有存储会话信息,并且有一个全新的会话 ID。我怀疑客户端上没有设置 cookie,情况似乎确实如此,这应该可以解释缺乏一致会话的原因。
However, I cannot figure out whyno new cookie is being set. Is there something wrong with how the app is configured that would indicate why this is happening?
但是,我无法弄清楚为什么没有设置新的 cookie。应用程序的配置方式是否有问题表明为什么会发生这种情况?
I should add that restarting the Node.js instance fixes the issue, it's just not something that would be tolerable in production.
我应该补充一点,重新启动 Node.js 实例可以解决这个问题,这在生产中是无法容忍的。
Thanks.
谢谢。
UPDATE: I ran Fiddler to see what was happening with HTTP/S traffic, and I can see that when it works initially, I'm getting a cookie set in the browser (I tried several) which is then passed back to the server on subsequent requests.
更新:我运行 Fiddler 以查看 HTTP/S 流量发生了什么,我可以看到,当它最初工作时,我在浏览器中设置了一个 cookie(我尝试了几个),然后将其传递回服务器后续请求。
When it doesn'twork, the browser is not passing cookies to the server, and so Node is sending a Set-Cookie header that provides a new cookie each time. So far I've had no luck determining the cause of this.
当它不起作用时,浏览器不会将 cookie 传递给服务器,因此 Node 会发送一个 Set-Cookie 标头,每次都会提供一个新的 cookie。到目前为止,我还没有确定原因。
回答by creativename
I figured it out, although I don't love the answer.
我想通了,虽然我不喜欢答案。
tl;dr; - use maxAge instead of expires.
tl;博士; - 使用 maxAge 而不是 expires。
The issue was rooted in the expiration date set on each cookie (which is automatically set by Express). I noticed that every cookie that was set had the same expiration date, which eventually ended up being in the past and hence instantly expiring.
该问题的根源在于每个 cookie 上设置的到期日期(由 Express 自动设置)。我注意到设置的每个 cookie 都有相同的到期日期,最终都成为过去,因此立即到期。
The cause of that was here:
原因在这里:
cookie: { expires : new Date(Date.now() + 3600000) }
The new Date was being created only once, upon server start. That was causing the expiration date to be the same every time. Based on code in the original post, I can't figure out why it doesn't work and yet every example I've found online uses the exact same code. I verified this by defining a function that created this Date, and checking that it only got called upon server start.
新日期仅在服务器启动时创建一次。这导致每次的到期日期都相同。根据原始帖子中的代码,我无法弄清楚为什么它不起作用,但我在网上找到的每个示例都使用完全相同的代码。我通过定义一个创建此日期的函数来验证这一点,并检查它是否仅在服务器启动时被调用。
To fix this issue, I am defining maxAge instead of "expires". maxAge takes a number of milliseconds, rather than a date, and it appears to be setting the expiration date on all cookies correctly.
为了解决这个问题,我定义了 maxAge 而不是“expires”。maxAge 需要几毫秒,而不是日期,并且它似乎正确设置了所有 cookie 的到期日期。
I would love to hear if anyone can explain why this is happening in the first place, since others seem to use it successfully. Any thoughts?
我很想听听是否有人能首先解释为什么会发生这种情况,因为其他人似乎成功地使用了它。有什么想法吗?
See my working code below
请参阅下面的我的工作代码
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.engine('html', consolidate.swig);
app.set('view engine', 'html');
swig.init({
root: '.',
allowErrors: true, // allows errors to be thrown and caught by express instead of suppressed
autoescape: false});
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser("[mysecrethere]"));
app.use(express.session({ store: sessionStore,
cookie: { maxAge : 3600000 } //1 Hour
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(expressValidator);
app.use(express.static(path.join(__dirname, 'public')));
//Dynamic helpers
app.use(require('./helpers/DynamicHelpers'));
app.use(app.router);
});
回答by AmirtharajCVijay
Set cookie name to value, where which may be a string or object converted to JSON. The path option defaults to "/".
将 cookie 名称设置为 value,其中可以是字符串或转换为 JSON 的对象。路径选项默认为“/”。
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
The maxAge option is a convenience option for setting "expires" relative to the current time in milliseconds. The following is equivalent to the previous example.
maxAge 选项是一个方便的选项,用于设置相对于当前时间(以毫秒为单位)的“过期”。下面的内容等同于前面的示例。
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
Also the Link
还有链接

