我正在使用本地策略验证带有express-validator和passport.js的登录表单:
login: function() {
passport.use('local-login', new LocalStrategy({
passReqToCallback: true
},
function(req, username, password, done) {
req.check('username', 'Incorrect user and/or password.').doesUserExists(password);
req.check('password', 'Password cannot be empty.').notEmpty();
req.asyncValidationErrors(true)
.then(function(user) {
return done(null, user);
})
.catch(function(errors) {
if (errors) return done(null, false, req.flash('error', errors));
});
}
));
}
函数doesUserExists()
是一个自定义异步验证,它为用户查询,比较数据库中散列密码提供的密码,并解析它:
doesUserExists: function(username, password) {
return new Promise(function(resolve, reject) {
User.findOne({ username: username })
.then(function(user) {
if (user) return user;
if (!user) reject(user);
})
.then(function(user) {
user.comparePassword(password, function(error, isMatch) {
if (isMatch) return user;
else reject(user);
});
resolve(user);
})
.catch(function(error) {
if (error) reject(error);
});
});
}
到目前为止它工作正常,除非用户和密码匹配,并且解析了promise,没有对象(用户)返回req.asyncValidationErrors()
函数,阻止其.then()
阻止重定向到用户个人资料。
我必须补充一点,我对承诺很新,不确定我期待的是否应该发生。也许对它如何运作的一些误解导致我认为是错误的。
目前,我决定对经过验证的用户/密码进行另一次数据库查询:
req.asyncValidationErrors(true)
.then(function() {
User.findOne({ username: username })
.then(function(user) {
return done(null, user);
});
})
.catch(function(errors) {
if (errors) {
return done(null, false, req.flash('error', errors));
}
});
额外的数据库查询并不优雅,但是......
答案 0 :(得分:1)
如果您只能返回User.find返回的Promise,则不需要创建新的Promise:
doesUserExists: function(username, password) {
return User.findOne({ username: username })
.then(function(user) {
if (user) {
// Also here is a mistake because we can't return inside
// the comparePassword callback, and that's why user is not get back
user.comparePassword(password, function(error, isMatch) {
if (isMatch) return user;
else throw new Error('my error');
});
}
else throw new Error('my error');
});
}
// Now use it as follows
req
.check('username', 'Incorrect user and/or password.')
.doesUserExists(username, password)
.then(function(user){/* user authenticated */})
.catch(function(error){/* user not atuhenticated */});
所以我猜你以后可以比较密码并解决问题:
doesUserExists: function(username, password) {
return User.findOne({ username: username })
.then(function(user) {
if (user) return user;
else throw new Error('my error');
});
}
// Now use it as follows
req
.check('username', 'Incorrect user and/or password.')
.doesUserExists(username, password)
.then(function(user){
/* From here, user was found */
user.comparePassword(password, function(error, isMatch) {
if (isMatch){ /* Do whatever with the user authenticated */ }
else { /* Do whatever you want when password don't match */ }
});
})
.catch(function(error){/* user not found */});
如果你正在做多个异步验证,我建议你使用Promise.all()来执行并行异步函数。