我使用node-bcrypt和PostgreSQL(通过Sequelizejs来哈希并保存密码。
用户的密码在beforeValidate
挂钩中进行哈希处理,如下所示:
beforeValidate: function(user, model, cb) {
bcrypt.hash(user.password, 10, function(err, hash) {
if ( err ) { throw err; }
user.password = hash;
cb(null, user);
});
}
存储哈希的User模型中的列定义为:
password: { type: DataTypes.STRING, allowNull: false }
当用户登录时(我使用Passport进行身份验证),该功能如下所示:
passport.use(new LocalStrategy(function(username, password, done) {
models.User.find({ username: username }).then(function(retrievedUser) {
if ( !_.isEmpty(retrievedUser) ) {
retrievedUser.verifyPassword(password, function(err, result) {
if ( err || !result ) {
return done(null, false, { message: 'Incorrect password.' });
} else {
return done(null, retrievedUser);
}
});
} else {
return done(null, false, { message: 'User could not be found at that username.' });
}
}).catch(function(err) {
return done(err);
});
}));
正确检索用户。
比较,在用户模型中定义:
instanceMethods: {
verifyPassword: function(password, cb) {
bcrypt.compare(password, this.password, cb);
}
}
如果密码只包含字母和/或符号,则验证通过正常。但是,任何带数字的密码都不会通过比较。有什么想法吗?
答案 0 :(得分:3)
在你的beforeValidate
函数中,你传递的是生成盐所需的盐,将该函数更改为
beforeValidate: function(user, model, cb) {
var salt = bcrypt.genSalt(10);
bcrypt.hash(user.password, salt, function(err, hash) {
if ( err ) { throw err; }
user.password = hash;
cb(null, user);
});
}
答案 1 :(得分:2)
嗯,令人尴尬(并且有些人怀疑),这与Bcrypt完全无关。
在我的身份验证功能中,我试图使用以下内容获取相应的用户:
models.User.find({ username: username })
但是,应该在where
字段中指定查询,如下所示:
models.User.find({
where: { username: username }
})
这导致身份验证方法始终与数据库中第一个用户的密码进行比较(默认情况下,在未指定where
字段时返回)。因此,它看起来很有效,因为第一个用户的字母密码始终有效,但没有后续密码有效(实际上,即使是只有字母的密码也会因其他用户而失败)。