【发布时间】:2022-01-12 11:36:45
【问题描述】:
我正在为 Web 应用程序实现身份验证,并希望实现忘记/重置密码功能,并且用户在重置密码时不应该输入旧密码。我的具体问题是这样的:
我有 1 个看起来像这样的猫鼬用户模型:
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
select: false,
},
passwordChangedAt: {
type: Date,
required: false,
default: null,
},
role: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Role',
required: true,
},
...Base,
});
我也有一个密码重置模型:
const PasswordResetSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
token: {
type: String,
required: true,
},
isUsed: {
type: Boolean,
required: false,
default: false,
},
expireDate: {
type: Date,
required: true,
},
oldPassword: {
type: String,
required: true,
},
newPassword: {
type: String,
required: false,
default: null,
},
...Base,
});
现在重置密码时,我想在密码重置表中查找,并检查 oldPassword 或 newPassword 之前是否已经使用过,如果使用过,则向用户显示他们曾经使用过该密码的错误。我使用bcrypt 使用盐对密码进行哈希处理,这意味着相同的密码可以在数据库中具有不同的哈希值。所以问题是在查询密码重置集合时,对于之前使用的相同密码,有没有办法在比较哈希和新的明文密码时查询密码以检查密码是否被使用。
const hashedPassword = await bcrypt.hash(password, bcrypt.genSaltSync());
// Here the hashedPassword is different, since the salt is different
const usedSamePassPreviously = await PasswordReset.find({
_id: { $nin: [passwordReset._id] },
user: user._id,
$or: [{ oldPassword: hashedPassword }, { newPassword: hashedPassword }],
isUsed: true,
});
我还尝试使用 mongo 中的 $where 子句进行查询,它允许我使用纯 JavaScript 函数,但是我们无法访问 bcrypt.compare 函数。我不想在后端加载所有数据,然后查找是否使用了密码,或者对所有密码使用相同的盐,因为这是一个安全问题。我如何处理这个查询,是否可以在数据库端实现这一点。提前致谢。
【问题讨论】:
-
// 从数据库中获取旧密码列表。如果匹配,则循环并承诺比较结果 BCRYPT.compare(req.body.newpassword, results[index].oldpassword, (err, result) => { // 如果匹配,则抛出错误...}; // 如果全部成功,没有进行比较,则创建新的哈希并插入它。
标签: javascript node.js mongodb mongoose bcrypt