为什么在 MongoDB versionKey "_v" 更改时 bcrypt 失败?
Why bcrypt fails when MongoDB versionKey "_v" is changed?
我正在尝试在 Nodejs 中实现身份验证流程。我正在使用 MongoDB 作为数据库,'bcrypt password hashing' 和 'mongoose document versioning' 有问题。
当我创建一个新帐户并使用该帐户登录时,没有任何问题,一切正常。但是当我对子文档进行更改时,versionKey“_v”正在更改并且我无法再访问该帐户。它向我抛出来自护照中间件的 'Invalid password' 错误。我不明白为什么会这样。
结构如下:
Mongoose 用户模型
const bcrypt = require("bcrypt");
const userSchema = new mongoose.Schema(
{
name: { type: String, required: true },
surname: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
username: { type: String },
bio: { type: String },
title: { type: String },
area: { type: String },
image: {
type: String,
default:
"https://icon-library.com/images/no-profile-pic-icon/no-profile-pic-icon-24.jpg",
},
experiences: [
{ type: mongoose.Schema.Types.ObjectId, ref: "Experience" },
],
friends: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
friendRequests: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
},
{ timestamp: true }
);
/**
* Enyrcyp user password before saving DB
*/
userSchema.pre("save", async function (next) {
try {
// const user = this;
// if (!user.isModified("password")) return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
} catch (error) {
console.log("Bcryp hash error: ", error);
next(error);
}
});
/**
* Checks entered password and hashed password in DB
* returns boolean
* @param {String} enteredPassword
*/
userSchema.methods.isValidPassword = async function (enteredPassword) {
try {
return await bcrypt.compare(enteredPassword, this.password);
} catch (error) {
console.log("Bcrypt password check error: ", error);
next(error);
}
};
const User = mongoose.model("User", userSchema);
module.exports = User;
处理用户登录过程的 Passport 中间件
passport.use(
new LocalStrategy(
{
usernameField: "email",
},
async (email, password, done) => {
try {
const foundUser = await db.User.findOne({ email });
if (!foundUser) throw new ApiError(400, "Invalid email ");
const isPasswordsMatched = await foundUser.isValidPassword(
password
);
if (!isPasswordsMatched)
throw new ApiError(400, "Invalid password");
//Send user if everything is ok
done(null, foundUser);
} catch (error) {
console.log("Passport local strategy error: ", error);
done(error, false);
}
}
)
);
我发现,如果我更改散列密码的逻辑,它就会起作用。我删除了在保存数据库之前向密码添加哈希的猫鼬预保存挂钩。
这是工作结构:
- 我刚刚将 mongoose hook 转换为方法
/**
* Enyrcyp user password before saving DB
*/
userSchema.methods.hashPassword = async function () {
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
} catch (error) {
console.log("Bcryp hash error: ", error);
next(error);
}
};
- 我在将新用户保存到数据库之前调用 hashPassword 函数。
因此,对于这种结构,我只在用户注册时使用一次 bcrypt。可能文档版本更改影响了 bcrypt 哈希。现在可以使用了。
我正在尝试在 Nodejs 中实现身份验证流程。我正在使用 MongoDB 作为数据库,'bcrypt password hashing' 和 'mongoose document versioning' 有问题。
当我创建一个新帐户并使用该帐户登录时,没有任何问题,一切正常。但是当我对子文档进行更改时,versionKey“_v”正在更改并且我无法再访问该帐户。它向我抛出来自护照中间件的 'Invalid password' 错误。我不明白为什么会这样。
结构如下:
Mongoose 用户模型
const bcrypt = require("bcrypt");
const userSchema = new mongoose.Schema(
{
name: { type: String, required: true },
surname: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
username: { type: String },
bio: { type: String },
title: { type: String },
area: { type: String },
image: {
type: String,
default:
"https://icon-library.com/images/no-profile-pic-icon/no-profile-pic-icon-24.jpg",
},
experiences: [
{ type: mongoose.Schema.Types.ObjectId, ref: "Experience" },
],
friends: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
friendRequests: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
},
{ timestamp: true }
);
/**
* Enyrcyp user password before saving DB
*/
userSchema.pre("save", async function (next) {
try {
// const user = this;
// if (!user.isModified("password")) return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
} catch (error) {
console.log("Bcryp hash error: ", error);
next(error);
}
});
/**
* Checks entered password and hashed password in DB
* returns boolean
* @param {String} enteredPassword
*/
userSchema.methods.isValidPassword = async function (enteredPassword) {
try {
return await bcrypt.compare(enteredPassword, this.password);
} catch (error) {
console.log("Bcrypt password check error: ", error);
next(error);
}
};
const User = mongoose.model("User", userSchema);
module.exports = User;
处理用户登录过程的 Passport 中间件
passport.use(
new LocalStrategy(
{
usernameField: "email",
},
async (email, password, done) => {
try {
const foundUser = await db.User.findOne({ email });
if (!foundUser) throw new ApiError(400, "Invalid email ");
const isPasswordsMatched = await foundUser.isValidPassword(
password
);
if (!isPasswordsMatched)
throw new ApiError(400, "Invalid password");
//Send user if everything is ok
done(null, foundUser);
} catch (error) {
console.log("Passport local strategy error: ", error);
done(error, false);
}
}
)
);
我发现,如果我更改散列密码的逻辑,它就会起作用。我删除了在保存数据库之前向密码添加哈希的猫鼬预保存挂钩。
这是工作结构:
- 我刚刚将 mongoose hook 转换为方法
/**
* Enyrcyp user password before saving DB
*/
userSchema.methods.hashPassword = async function () {
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
} catch (error) {
console.log("Bcryp hash error: ", error);
next(error);
}
};
- 我在将新用户保存到数据库之前调用 hashPassword 函数。
因此,对于这种结构,我只在用户注册时使用一次 bcrypt。可能文档版本更改影响了 bcrypt 哈希。现在可以使用了。