我需要一个像这个那样的登录时“记住我”复选框. 并且在使用passport之前添加中间件。
app.use(function(req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = 1000 * 60 * 3;
} else {
req.session.cookie.expires = false;
}
}
next();
});
app.use(passport.initialize());
app.use(passport.session());
当req.body.rememberme
为真时,我无法登录,而当req.body.rememberme
为假时,用户会被记住。
我还尝试了connect-ensure-login,但仍然有问题。
另外一个问题是:我应该在什么时候删除我的数据库中的cookie以及如何删除?
:)
其他代码与护照指南完全相同。
路由:
app.get('/', passport.authenticate('local', {
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/user/home');
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login'
}), function(req, res) {
res.redirect('/user/home');
});
会话:
passport.serializeUser(function(user, done) {
var CreateAccessToken = function() {
var token = user.GenerateSalt();
User.findOne({
accessToken: token
}, function(err, existingUser) {
if (err)
return done(err);
if (existingUser) {
CreateAccessToken();
} else {
user.set('accessToken', token);
user.save(function(err) {
if (err)
return done(err);
return done(null, user.get('accessToken'));
})
}
});
};
if (user._id)
CreateAccessToken();
});
passport.deserializeUser(function(token, done) {
User.findOne({
accessToken: token
}, function(err, user) {
if (err)
return done(err);
return done(err, user);
});
});
以及策略:
passport.use(new LocalStrategy(function(userId, password, done) {
User.findOne().or([{
username: userId
}, {
email: userId
}]).exec(function(err, user) {
if (err)
return done(err);
if (!user) {
return done(null, false, {
message: 'Invalid password or username'
});
}
if (user.Authenticate(password)) {
return done(null, user);
} else {
return done(null, false, {
message: 'Invalid password or username'
});
}
});
}));
我注意到Express只会在哈希值改变时更新Cookie,所以我更改了中间件的代码。
app.use(function(req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = 1000 * 60 * 3;
req.session._garbage = Date();
req.session.touch();
} else {
req.session.cookie.expires = false;
}
}
next();
});
现在我可以使用“记住我”功能登录,但它只能在Ubuntu上的chromium和firefox上工作。我仍然无法在Win7和Android上的chrome和firefox上勾选“记住我”复选框进行登录。
当我在Win7上的chrome上POST到“/login”时,我检查了响应头,它与Ubuntu上相同具有相同的“Set-Cookie”字段,为什么它不能工作?
时间不同步...所以我提交了一个额外的时间字段。
$('#login').ajaxForm({
beforeSubmit: function(arr, $form, option) {
arr.push({
name: '__time',
value: (new Date()).toGMTString()
});
}
});
以及“RememberMe”中间件:
app.use(function(req, res, next) {
if (req.method == 'POST' && req.url == '/login') {
if (req.body.rememberme) {
req.session.cookie.maxAge = moment(req.body.__time).add('m', 3) - moment();
req.session._garbage = Date();
req.session.touch();
} else {
req.session.cookie.expires = false;
}
}
next();
});
rememberme == true
,则Cookie将会有一个到期时间(在这种情况下为3分钟),否则该Cookie将被设置为会话Cookie(当浏览器会话结束时到期)。但我同意:需要更多的代码。 - robertklepserialize
和deserialize
函数只用于通过用户id(使用数据库id)获取用户并将其序列化为会话cookie(如果您担心,id不会以明文形式存在)。不要混杂一些可疑的安全代码。 - pfriedserialize
中我创建了一个唯一的令牌,并在deserialize
中找到了用户获得的令牌,但我不清楚这些函数何时被调用。 - QingYun