bcrypt.compare() 在验证密码时总是返回 false

Posted

技术标签:

【中文标题】bcrypt.compare() 在验证密码时总是返回 false【英文标题】:bcrypt.compare() always returns false when verifying passwords 【发布时间】:2014-05-30 07:56:11 【问题描述】:

我关注了来自 scotch.io 的this tutorial,了解如何使用 node.js 构建用户身份验证(顺便说一句,教程很棒)。但是,当调用verifyPassword(password) 来检查用户密码时,由于某种原因,该值总是返回为false。

我将 brcypt.js 和 sequelize.js 用于我的 express 项目。

模型用户的自定义方法:

classMethods : 

     setPassword : function(password) 

          return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);

    

,
instanceMethods: 

     verifyPassword: function(password) 
           return bcrypt.compare(password, this.password, function(err, result) 

            if (err) throw err;
            return result;

          );
    

   

这就是我创建新用户的方式:

User.find(where: email : email)
    .complete(function(err, user) 

  // if there are any errors, return the error
  if (err)
      return done(err);
  

  // check to see if theres already a user with that email
  if (user) 
     return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
   else 


            User
              .create(
                email: email,
                password: User.setPassword(password)

              )
              .complete(function(err, newUser) 
                if (err) 
                    throw err;
                return done(null, newUser)
        )


         

); 

验证密码:

User.find(where:  email :  email )
        .complete(function(err, user) 

        if (err)
            return done(err);

        if (!user)

            return done(null, false, req.flash('loginMessage', 'No user found.')); 
        
        // if the user is found but the password is wrong

        if (!user.verifyPassword(password))

            return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
        
        // all is well, return successful user
        return done(null, user);
    );

我知道在 bcrypt 中使用异步模式会更好,但是当我尝试这样的事情时它总是给我“密码未定义”:

setPassword : function(password) 
    return bcrypt.genSalt(10, function(err, salt) 
            if (err) return err;
        return bcrypt.hash(password, salt, function(err, hash) 
                if (err) return err;
                return hash;
        );
    );
 

我应该怎么做?

【问题讨论】:

【参考方案1】:

bcrypt.compare 似乎是异步的,你应该扩展你的比较函数来接受回调。

您可以对 setPassword 执行相同的操作,但您必须在回调中进行创建。您现在正在同步问题中使用它,因此它必须是同步函数。

你可以这样做:

classMethods : 
  setPassword : function(password, callback)        
    // Pseudo, i don't actually know the bcrypt api
    return bcrypt.hash(password, bcrypt.genSaltSync(8), callback);
  
,
instanceMethods: 
  verifyPassword: function(password, callback) 
    bcrypt.compare(password, this.password, callback);
  

然后将您的接口代码重写为:

Uset.setPassword(password, function (err, password) 
  if (err) return done(err);
  User.create(
    email: email,
    password: password
  ).done(done);
);

user.verifyPassword(password, function (err, result) 
  if (err || result) return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
  return done(null, user);
);

在创建时加密密码是钩子派上用场的地方,您可以使用 beforeCreate 钩子在密码保存之前加密密码,而不是自己处理加密。

User.beforeCreate(function (model, done) 
  bcrypt.hash(model.password, bcrypt.genSaltSync(8), function (err, password) 
    if (err) return done(err);
    model.password = password;
    done();
  );
);

User.create(
  email: email,
  password: password // Unencrypted
);

before create 将确保在将值插入数据库之前对其进行加密。

【讨论】:

感谢您的快速回复。我根据你的回答做了修改。但无论密码是否正确,用户始终可以登录。此外,结果始终返回为 false 我不知道如何使用 beforeCreate 方法。我是否也应该在模型中将其声明为 classMethod 并在我想创建用户时调用它?谢谢 嗨,我解决了这个问题。原来这是我的setter方法。我将其设置为: this.setDataValue('password', newPassword.toString().toLowercase) 等哈希都转换为小写。感谢您的帮助! 不,你在模型上声明了钩子,就像我在示例中提供的那样。很高兴您解决了您的问题。 天哪!我遇到了同样的问题。感谢您提及小写设置器。

以上是关于bcrypt.compare() 在验证密码时总是返回 false的主要内容,如果未能解决你的问题,请参考以下文章

无论密码如何,Bcrypt-NodeJS compare() 都会返回 false

bcrypt.compare() 是异步的,这是不是一定意味着肯定会发生延迟? [复制]

尝试在打字稿中使用猫鼬和 bcrypt 比较密码

bcrypt.compare() 或 bcrypt.compareSync()

如何从firebase中的电子邮件中获取用户信息

护照和猫鼬的bcrypt错误