【问题标题】:bcrypt compare returning false when password contains numbers当密码包含数字时,bcrypt 比较返回 false
【发布时间】:2015-01-18 14:49:52
【问题描述】:

我正在使用 node-bcrypt 和 PostgreSQL(通过 Sequelizejs 散列和保存密码。

用户的密码在 beforeValidate 钩子中散列,如下所示:

beforeValidate: function(user, model, cb) {
        bcrypt.hash(user.password, 10, function(err, hash) {
          if ( err ) { throw err; }
          user.password = hash;
          cb(null, user);
        });
      }

用户模型上存储哈希的列定义为:

password: { type: DataTypes.STRING, allowNull: false }

当用户登录时(我使用Passport进行身份验证),函数如下所示:

passport.use(new LocalStrategy(function(username, password, done) {
    models.User.find({ username: username }).then(function(retrievedUser) {
      if ( !_.isEmpty(retrievedUser) ) {
        retrievedUser.verifyPassword(password, function(err, result) {
          if ( err || !result ) {
            return done(null, false, { message: 'Incorrect password.' });
          } else {
            return done(null, retrievedUser);
          }
        });
      } else {
        return done(null, false, { message: 'User could not be found at that username.' });
      }
    }).catch(function(err) {
      return done(err);
    });
  }));

正确检索用户。

以及在用户模型上定义的比较:

instanceMethods: {
      verifyPassword: function(password, cb) {
        bcrypt.compare(password, this.password, cb);
      }
    }

如果密码仅包含字母和/或符号,则验证通过。但是,任何带有数字的密码都不会通过比较。有什么想法吗?

【问题讨论】:

  • 你确定数据库中的哈希值是正确的吗?也许您在创建哈希之前不小心将密码小写了?
  • @loganfsmyth 只是仔细检查以确保这不是问题,并且看起来大写字母实际上可以正常工作。问题只是符号和数字(编辑过的原始帖子)
  • 您使用的是哪个模块?有许多 bcrypt 实现。
  • @AaronDufour 我正在使用在我的原始帖子here 中链接的实现。我相信这是官方的节点实现?
  • 我认为这与 bcrypt 无关。由于 JS 中的自动类型转换,我假设您的字母密码仅匹配。如果您能提供在这两种情况下提供给哈希调用的准确输入,将会很有帮助。

标签: javascript node.js express bcrypt


【解决方案1】:

好吧,令人尴尬的是(正如一些人所怀疑的那样),这与 Bcrypt 完全无关。

在我的身份验证功能中,我尝试使用以下内容获取适当的用户:

models.User.find({ username: username })

但是,查询应该在 where 字段中指定,如下所示:

models.User.find({
   where: { username: username }
})

这导致身份验证方法始终与数据库中第一个用户的密码进行比较(未指定 where 字段时默认返回)。因此,它似乎可以工作,因为第一个用户的纯字母密码始终有效,但后面的密码无效(实际上,即使其他用户的纯字母密码也会失败)。

【讨论】:

    【解决方案2】:

    在您的 beforeValidate 函数中,您传入 10 作为生成盐所需的盐,将该函数更改为此

    beforeValidate: function(user, model, cb) {
        var salt = bcrypt.genSalt(10);
        bcrypt.hash(user.password, salt, function(err, hash) {
          if ( err ) { throw err; }
          user.password = hash;
          cb(null, user);
        });
      }
    

    【讨论】:

    • 我认为可能也是这样,但文档说:“salt - [REQUIRED] - 用于散列密码的盐。如果指定为数字,则将生成盐并使用(见示例)。”并不是说它不会导致问题(我没有测试它),但它似乎是允许的。
    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2018-11-28
    • 1970-01-01
    • 2017-09-16
    • 2020-05-24
    相关资源
    最近更新 更多