【问题标题】:Weird issue with devise valid_password?设计valid_password的奇怪问题?
【发布时间】:2016-03-12 04:50:32
【问题描述】:

在过去的 2 小时里,我一直在尝试调试设计中的一个奇怪问题,该问题不允许我登录。

这也是我所指的东西:

password 
=> 'vinodsobale'

password == 'vinodsobale'
=> true

resource.valid_password?(password)

=> false

resource.valid_password?('vinodsobale')

=> true

附上截图:

注意:我在 devise 中启用了调试器,所以上面的代码是 devise 内部代码。

对我来说,这似乎是Devise.secure_compare 中的一个问题。

【问题讨论】:

  • 打开 GitHub 问题?最好使用可重复的测试。
  • @Viren - 我对 ruby​​ 或设计一无所知,但我会检查给定密码的编码。
  • 你能做一个password.encoding 并告诉我们结果吗?这是我唯一能想到的出错的地方。您还可以使用::BCrypt::Engine.hash_secret(password, salt) 并将其与实际存储的哈希值进行比较。对于这种比较,text.bytes 也可能会派上用场。
  • 您能检查一下password.bytes 和'vinodsobale'.bytes 以确认一下吗?
  • @lad2025,你说的“得救”是什么意思?是password 吗?如果是,NULL character \0 应编码为 un​​icode,password == 'vinodsobale' 不应返回 true。

标签: ruby-on-rails devise ruby-on-rails-3.2


【解决方案1】:

此问题是由 Ruby 2.2.0 中的一个已知字符串损坏错误导致的,即 2.2.2 中的 fixed。

如bug report 中所述,当 BCrypt 从其 C 扩展调用特定的字符串创建 API 时发生损坏,该 API 通过从 Devise::Models::DatabaseAuthenticatable#valid_password? 方法调用 ::BCrypt::Engine.hash_secret 触发 Devise v3.3.0。针对此错误的特定于设计的workaround 已在 v3.5.0 中发布。

解决办法是:

  • 将 Ruby 降级到 < 2.2.0,或升级到 >= 2.2.2;
  • 将设计升级到>= 3.5.0。

【讨论】:

    【解决方案2】:

    这可能是原始源和控制台之间的编码问题。如果你运行password.codepoints,你应该能够看到实际的编码。在原始“密码”字符串上运行 .codepoints 应返回 [112, 97, 115, 115, 119, 111, 114, 100]。

    【讨论】:

      【解决方案3】:

      设计DatabaseAuthenticatable#valid_password? 正在使用一个名为Encryptor::compare 的方法,它需要2 个对象,当前存储的密码和您要比较的新密码,我相信这种方法有一个副作用,即修改第二个参数中间所以它会修改对象而不是一次它会被修改两次,这会导致错误的结果,所以如果你传递了一个重复的密码对象,它可能会起作用。 可以试试valid_password? password.dup

      【讨论】:

      • 如果是这种情况,为什么在提供字符串时不会发生修改 resource.valid_password?('vinodsobale') 每次我以前运行它时它都可以工作,return true
      【解决方案4】:

      怎么样

      resource.valid_password?(password.to_s)
      

      希望对你有帮助。

      【讨论】:

      • 请编辑您的帖子并解释为什么会这样。
      • 为什么你认为这会起作用我首先看到了很多问题我已经提到了,即password == 'vinodsobale' 匹配。如果vinodsoble 是string 类型(我们都可以看到),那么password 也是string,所以.to_s 不会产生任何不同。其次,您刚才提到的代码是设计内部代码的一部分,您希望如何实现它,例如打开设计代码并对其进行猴子补丁。
      • 如果右边有无效类型,可能是equal运算符自动调用to_s方法。但我只是猜测。你试过了吗?
      • 这是一个合理的解释。
      • 你使用了password == 'vinosobale'。你能试试password === 'vidodsobale' 匹配吗?你能看一下这个问题吗——stackoverflow.com/questions/7156955/…?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多