我正在使用标准的本地策略进行身份验证.
//------------- //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,{ 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,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);
和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'); } }
我可以通过调试找到,认证成功后(cookie过期后),我按这个逻辑(从上面):
function(req,res) { var targetUrl = req.session.pageAfterLogin; delete req.session.pageAfterLogin; res.redirect(targetUrl || '/account'); }
在哪里可以看到“req”会话正确设置,护照信息存储正确.然后,发生重定向,新请求没有存储会话信息,并且具有全新的会话ID.我怀疑客户端上没有设置cookie,这似乎是这样,这应该解释缺乏一致的会话.
但是,我不知道为什么没有设置新的cookie.应用程式如何配置出现问题,表明为什么会发生这种情况?
我应该补充说,重新启动Node.js实例来修复这个问题,这不仅仅是生产中容忍的东西.
谢谢.
更新:我运行了fiddler来看看HTTP / S的流量发生了什么,我可以看到,当它最初工作时,我在浏览器中设置了一个cookie(我尝试了几个),然后将其传回给服务器后续请求.
当它不起作用时,浏览器不会将cookie传递到服务器,因此Node发送一个Set-Cookie头,每次都提供一个新的cookie.到目前为止,我没有运气确定这个原因.
解决方法
TL;博士; – 使用maxAge而不是expires.
该问题植根于每个Cookie设置的有效期(由Express自动设置).我注意到,所设置的每个cookie都有相同的到期日期,最终终止于过去,因此立即过期.
原因在于:
cookie: { expires : new Date(Date.Now() + 3600000) }
服务器启动后,新的日期只会被创建一次.这是导致到期日期相同的每一次.根据原始帖子中的代码,我不知道为什么它不起作用,但是我在网上找到的每个例子都使用完全相同的代码.我通过定义一个创建此Date的函数来验证这一点,并检查它仅在服务器启动时被调用.
为了解决这个问题,我定义了maxAge而不是“expires”. maxAge需要几毫秒而不是日期,并且正好在所有的cookie上设置到期日.
我很乐意听到有人可以解释为什么这是发生在第一位,因为其他人似乎成功使用它.有什么想法吗?
请看我下面的工作代码
app.configure(function(){ app.set('port',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); });