如何在mongoose API调用中嵌入bcrypt?

sg24os4d  于 12个月前  发布在  Go
关注(0)|答案(1)|浏览(131)

设置

我正在做网站授权,并希望将最佳实践嵌入其中,同时保持代码整洁和可读性。现在我有这样的经典代码:

let foundUser = await userModel.findOne({ email: recievedEmail });
if(!foundUser)
    error("not authorized!");
const isPasswordMatch = await bcrypt.compare(recievedPassword, foundUser.password);
if(!isPasswordMatch)
    error("not authorized!");
foundUser.update({ $set: { lastLogin: new Date() }, $push: { myEvents: authEvent } });
foundUser.save();
success("authorized OK!");

字符串
同时,我在best mongoose command to perform auth上问了一个问题,我们以“原子”方式伪造了以下“auth-check-and-update”命令:

const foundUser = await userModel.findOneAndUpdate(
    { email: recievedEmail, password: recievedPassword },
    { $set: { lastLogin: new Date() }, $push: { myEvents: authEvent } }
);
if(foundUser)
    success("authorized OK!");
else
    error("not authorized!");


这里的想法是显而易见的-如果找到一个用户 * 与匹配的电子邮件和密码 *,那么用户 * 被认为是授权的 *,其 * 最后登录时间戳被更新 *(同时)。

问题

为了合并结合上述两种最佳实践,我需要以某种方式将bcrypt.compare()调用嵌入到findOneAndUpdate()调用中。这很棘手,因为我不能只是“比较哈希密码”; bcrypt只是与简单的哈希(如sha或md5)不同:For security reasons it returns different hashes every time。(链接中的答案解释了“为什么和如何”)。

解决方案尝试

我看了一下mongoose-bcrypt包:它使用了Schema.pre()功能:

schema.pre('update', preUpdate);
 schema.pre('findOneAndUpdate', preUpdate);


要了解这个想法,请看一下mongoose-bcrypt\index.js。你会看到,preUpdate只影响创建新用户(.. andUpdate部分),但不影响实际检查(findOne..部分)。所以这个插件可以适合实现“用户注册”/“更改密码”。但它不能以建议的方式进行授权。

提问

在这种情况下,您将如何“组合合并”bcrypt.compare()userModel.findOneAndUpdate()呼叫?

9avjhtql

9avjhtql1#

像这样在UserModel中比较密码怎么样

// method to compare password input to password saved in database
UserModel.methods.isValidPassword = async function(password){
    const user = this;
    const compare = await bcrypt.compare(password, user.password);
    return compare;
}

字符串
在你的auth或passport(我用的是passport)里面做一些这样的事情。

passport.use(new LocalStrategy(
    (username, password, done) => {
        // change your query here with findOneAndUpdate
        User.findOne({ username: username }, (err, user) => {
            if (err) { return done(err); }
            if (!user) {

                return done(null, false, { message: 'Incorrect username.' });
            }
            if (!user.isValidPassword(password)) {

                return done(null, false, { message: 'Incorrect password.' });
            }
            return done(null, user);
        });
    }
));

相关问题