我跟踪scotch.io中的this tutorial关于如何使用node.js构建用户身份验证(顺便说一下,很棒的教程)。但是,当调用verifyPassword(password)
来检查用户密码时,由于某种原因,该值始终返回false。
我使用brcypt.js和sequelize.js作为我的快递项目。
classMethods : {
setPassword : function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
}
},
instanceMethods: {
verifyPassword: function(password) {
return bcrypt.compare(password, this.password, function(err, result) {
if (err) throw err;
return result;
});
}
}
User.find({where: {email : email}})
.complete(function(err, user) {
// if there are any errors, return the error
if (err){
return done(err);
}
// check to see if theres already a user with that email
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
User
.create({
email: email,
password: User.setPassword(password)
})
.complete(function(err, newUser) {
if (err)
throw err;
return done(null, newUser)
})
}
});
User.find({where: { email : email }})
.complete(function(err, user) {
if (err)
return done(err);
if (!user){
return done(null, false, req.flash('loginMessage', 'No user found.'));
}
// if the user is found but the password is wrong
if (!user.verifyPassword(password)){
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
// all is well, return successful user
return done(null, user);
});
我知道在bcrypt中使用异步模式会更好,但它始终会给我"密码未定义"当我尝试这样的事情时:
setPassword : function(password) {
return bcrypt.genSalt(10, function(err, salt) {
if (err) return err;
return bcrypt.hash(password, salt, function(err, hash) {
if (err) return err;
return hash;
});
});
}
我该怎么做呢?
答案 0 :(得分:1)
bcrypt.compare似乎是异步的,您应该扩展比较函数以进行回调。
您可以对setPassword执行相同操作,但您必须在回调中进行创建。您现在正在同步问题中使用它,因此它必须是同步函数。
您可以执行以下操作:
classMethods : {
setPassword : function(password, callback) {
// Pseudo, i don't actually know the bcrypt api
return bcrypt.hash(password, bcrypt.genSaltSync(8), callback);
}
},
instanceMethods: {
verifyPassword: function(password, callback) {
bcrypt.compare(password, this.password, callback);
}
}
然后将您的接口代码重写为:
Uset.setPassword(password, function (err, password) {
if (err) return done(err);
User.create({
email: email,
password: password
}).done(done);
});
user.verifyPassword(password, function (err, result) {
if (err || result) return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
return done(null, user);
});
在create上加密密码是钩子派上用场的地方,而不是自己处理加密,你可以使用beforeCreate挂钩在保存之前加密密码。
User.beforeCreate(function (model, done) {
bcrypt.hash(model.password, bcrypt.genSaltSync(8), function (err, password) {
if (err) return done(err);
model.password = password;
done();
});
});
User.create({
email: email,
password: password // Unencrypted
});
然后,在创建之前,确保该值在插入数据库之前已加密。