【问题标题】:Has_secure_password Bcrypt giving nil passwordHas_secure_password Bcrypt 给出零密码
【发布时间】:2021-04-10 03:05:18
【问题描述】:

我正在尝试跟随 Michael Hartl 的 Ruby on Rail 一书,我在第 10 章,尝试允许用户编辑他们的配置文件设置,这是最奇怪的错误 - bcrypt 的 password_digest 正在破坏我的测试。

users.yml

user:
  name: Example User
  email: example@gmail.com
  password_digest: <%= User.digest("password") %>

当我在 Rails 控制台中运行它时,这就是我所看到的

user.valid? => false

user.errors.full_messages => ["密码不能为空", "密码太短(最少6个字符)"]

user.rb

class User < ApplicationRecord
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  before_save {
   self.email.downcase!
  }

  validates :name, presence: true, length: { maximum: 50 }
  validates :email, presence: true, length: { maximum: 255 },
            format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
  validates :password, presence: true, length: { minimum: 6 }
  has_secure_password

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
               BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end
end

我使用的是 bcrypt 版本 '3.1.11'

我的测试代码

 def setup
    @user = users(:marko)
  end

  test "successful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    name = "Foo bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: {
                                          name: name,
                                          email: email,
                                          password: "password",
                                          password_confirmation: "password" } }
    assert_not flash.empty?
    assert_redirected_to @user
    follow_redirect!
    @user.reload
    assert_equal name, @user.name
    assert_equal email, @user.email
  end

有什么想法可能是错的吗?

【问题讨论】:

  • 尝试在 yml 中提供 password。摘要应该是自动创建的。
  • 试过这个,我得到ActiveRecord::Fixture::FixtureError: table "users" has no column named "password"
  • 你的测试代码怎么样?
  • 将我的测试代码添加到问题中,尽管我能够在控制台中复制问题
  • 好的,所以我决定不做一些完全不相关的事情就继续前进。由于某些莫名其妙的原因-测试自行修复。虽然这是有道理的,因为我在互联网上找到的任何东西都没有困扰我的代码,但我很犹豫,因为问题是随机出现的。 TL;DR-这个问题没有答案。目前,问题已解决。

标签: ruby-on-rails ruby bcrypt


【解决方案1】:

试试下面的代码

user:
  name: Example User
  email: example@gmail.com
  password: "password"

Bcrypt 已验证 password attr_accessor 在创建新记录时应该存在(更新时可选)。

您还应该将allow_blank: true 添加到您的length validation 作为密码,因为当密码本身为empty/nil

时不需要长度验证

【讨论】:

    【解决方案2】:

    拥有这样的灯具:

    some_user:
      name: Some user
      email: some_user@example.com
      password_digest: <%= BCrypt::Password.create('secret') %>
    

    将使用该数据直接创建一个用户到数据库。

    那么在验证模型时,你必须实现这样的验证:

    validates :password, length: { minimum: 6, allow_blank: true }
    

    请注意,您不应验证 presence

    这是因为在表单中您将要求使用该名称的 password,而不是 password_digest(这是保存到 DB 表中的最后一个字段)。

    Rails 将验证“假”或中间密码字段,如果通过,则生成摘要并将密码字段排除在外。这就是为什么你必须添加allow_blank: true,这样测试才能通过。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2018-08-25
      • 2017-01-03
      相关资源
      最近更新 更多