Node.js 无论密码是什么,Bcrypt NodeJS compare()都返回false
我知道这个问题已经被问过好几次了(比如,或者,甚至是在,但是没有一个答案对我有效 我正在尝试使用Mongoose和Passport为NodeJS应用程序开发身份验证,并使用Bcrypt NodeJS散列用户密码 在我决定重构用户模式并使用bcrypt的异步方法之前,一切都正常工作。创建新用户时哈希仍然有效,但我现在无法根据MongoDB中存储的哈希验证密码 我知道什么?Node.js 无论密码是什么,Bcrypt NodeJS compare()都返回false,node.js,mongoose,bcrypt,Node.js,Mongoose,Bcrypt,我知道这个问题已经被问过好几次了(比如,或者,甚至是在,但是没有一个答案对我有效 我正在尝试使用Mongoose和Passport为NodeJS应用程序开发身份验证,并使用Bcrypt NodeJS散列用户密码 在我决定重构用户模式并使用bcrypt的异步方法之前,一切都正常工作。创建新用户时哈希仍然有效,但我现在无法根据MongoDB中存储的哈希验证密码 我知道什么? bcrypt.compare() 在用户创建密码时,密码只会散列一次(因此不会重新散列) 提供给compare方法的密码和散列
bcrypt.compare()
var userSchema = mongoose.Schema({
// Local authentication
password: {
hash: {
type: String,
select: false
},
modified: {
type: Date,
default: Date.now
}
},
// User data
profile: {
email: {
type: String,
required: true,
unique: true
}
},
// Dates
lastSignedIn: {
type: Date,
default: Date.now
}
});
密码散列
密码比较
用户身份验证
这可能是我犯的一个“简单”的错误,但我没能在几个小时内发现任何错误……也许你有什么想法使这种方法起作用,我很乐意阅读
谢谢你们
编辑:
当运行这段代码时,match实际上等于true
。因此我知道我的方法是正确的。我怀疑这与哈希在数据库中的存储有关,但我真的不知道是什么导致了此错误的发生
var pwd = 'TestingPwd01!';
mongoose.model('User').hashPassword(pwd, function(err, hash) {
console.log('Password: ' + pwd);
console.log('Hash: ' + hash);
user.password.hash = hash;
user.comparePassword(pwd, function(err, match) {
console.log('Match: ' + match);
});
});
编辑2(和解决方案):
我把它放在那里,以防有一天它会对某人有所帮助
我在我的代码中发现了错误,这是在用户注册期间发生的(实际上是我唯一没有在这里发布的代码)。我正在散列user.password
对象,而不是user.password.plaintext
只有将依赖项从“brcypt nodejs”更改为“bcryptjs”,我才能找到错误,因为当要求bcryptjs散列对象时,bcryptjs会抛出一个错误,而brcypt nodejs只是将对象散列为字符串。有3个参数……出于某种原因,您有4个参数
而不是
bcrypt.hash(password, bcrypt.genSaltSync(12), null, function(err, hash) {
应该是
bcrypt.hash(password, bcrypt.genSaltSync(12), function(err, hash) {
由于您仅在用户创建期间进行哈希运算,因此可能没有正确进行哈希运算。您可能需要重新创建用户。我知道已经找到了解决方案,但以防您从google搜索中登录到这里,并遇到同样的问题,尤其是如果您使用的是schema.pre(“保存”)函数,有时会多次保存同一个模型,因此每次都会对密码进行哈希处理。如果您使用mongoDB中的引用来创建架构关系,则尤其如此。下面是我的注册函数的外观: 注册代码
User.create(newUser, (err, user) => {
if (err || !user) {
console.warn("Error at stage 1");
return res.json(transformedApiRes(err, "Signup error", false)).status(400);
}
let personData: PersonInterface = <PersonInterface>{};
personData.firstName = req.body.first_name;
personData.lastName = req.body.last_name;
personData.user = user._id;
Person.create(personData, function (err1: Error, person: any): any {
if (err1 || !person) {
return res.json(transformedApiRes(err1, "Error while saving to Persons", false));
}
/* One-to-One relationship */
user.person = person;
user.save(function (err, user) {
if (err || !user) {
return res.json({error: err}, "Error while linking user and person models", false);
}
emitter.emit("userRegistered", user);
return res.json(transformedApiRes(user, `Signup Successful`, true));
});
});
});
UsersSchema.pre("save", function (next: NextFunction): any {
let user: any = this;
if (user.isModified("password") || user.isNew) {
bcrypt.genSalt(10, function (err: Error, salt: string): any {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function (err: Error, hash: string) {
if (err) {
console.log(err);
return next(err);
}
console.warn({plain: user.password, hash: hash});
user.password = hash;
next();
});
});
} else {
return next();
}
});
修复,解决方案
要解决此问题,您必须修改预(“保存”)代码,以确保密码仅在第一次保存到数据库或密码已被修改时才进行哈希处理。为此,请将预保存代码包围在以下块中:
if (user.isModified("password") || user.isNew) {
//Perform password hashing here
} else {
return next();
}
以下是我的整个预保存功能的样子
User.create(newUser, (err, user) => {
if (err || !user) {
console.warn("Error at stage 1");
return res.json(transformedApiRes(err, "Signup error", false)).status(400);
}
let personData: PersonInterface = <PersonInterface>{};
personData.firstName = req.body.first_name;
personData.lastName = req.body.last_name;
personData.user = user._id;
Person.create(personData, function (err1: Error, person: any): any {
if (err1 || !person) {
return res.json(transformedApiRes(err1, "Error while saving to Persons", false));
}
/* One-to-One relationship */
user.person = person;
user.save(function (err, user) {
if (err || !user) {
return res.json({error: err}, "Error while linking user and person models", false);
}
emitter.emit("userRegistered", user);
return res.json(transformedApiRes(user, `Signup Successful`, true));
});
});
});
UsersSchema.pre("save", function (next: NextFunction): any {
let user: any = this;
if (user.isModified("password") || user.isNew) {
bcrypt.genSalt(10, function (err: Error, salt: string): any {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function (err: Error, hash: string) {
if (err) {
console.log(err);
return next(err);
}
console.warn({plain: user.password, hash: hash});
user.password = hash;
next();
});
});
} else {
return next();
}
});
希望这能帮助别人。我把这个放在这里,因为它可能有一天会帮助别人 在我自己的例子中,即使我提供了正确的身份验证详细信息,我仍将
bcrypt.compare设置为false
的原因是因为模型中的数据类型受到限制。因此,每次将哈希保存在数据库中时,它都会被截断,以适应50
字符的限制
我有
'password': {
type: DataTypes.STRING(50),
allowNull: false,
comment: "null"
},
该字符串只能包含50个字符
,但bcrypt.hash
的结果不止这些
修复
我修改了模型,因此
DataTypes.STRING(255)
提示:如果您正在切换
then().then()
Block always check返回值。我正在使用该模块(我在Windows机器上工作,不想安装多个Gig的依赖项…)哪个hash()方法有4个参数,第三个参数是一个回调,用于表示哈希过程中的进度。您的建议使我的应用程序抛出错误,因为没有给出回调。无论如何,谢谢,我可能会切换到“真正的”bcrypt包(您在这里提到的那个)或者更好,使用Windows以外的软件来开发我的应用程序。@Antoinevanservey这是我的错。太多的bcrypt模块,例如。如果您正在寻找替代方案,我可能会推荐最后一个,因为它通常适用于所有平台。@Mickey没问题。我会看看bcryptjs,谢谢您的建议。您应该这样做如果答案不符合你的要求,就不要标出最佳答案question@raam86我找到解决方案是因为对答案的评论,这不是最好的答案吗?不?好的,我会记住的。
UsersSchema.pre("save", function (next: NextFunction): any {
let user: any = this;
if (user.isModified("password") || user.isNew) {
bcrypt.genSalt(10, function (err: Error, salt: string): any {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function (err: Error, hash: string) {
if (err) {
console.log(err);
return next(err);
}
console.warn({plain: user.password, hash: hash});
user.password = hash;
next();
});
});
} else {
return next();
}
});
'password': {
type: DataTypes.STRING(50),
allowNull: false,
comment: "null"
},