Has_secure_password Bcrypt给出空密码

3

我正在尝试跟随Michael Hartl的Ruby on Rails书籍,并且现在在第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中仅提供“密码”。摘要应该自动生成。 - max pleaner
尝试过这个,但是出现了 ActiveRecord::Fixture::FixtureError: table "users" has no column named "password" 的错误。 - degenPenguin
你的测试代码怎么样? - Daniel
将我的测试代码添加到问题中,尽管我能够在控制台中复制该问题。 - degenPenguin
好的,所以我决定在没有测试的情况下继续做一些完全无关的事情。出乎意料的是,测试问题自己解决了。虽然这很有道理,因为我在互联网上找到的所有东西都没有困扰我的代码,但我还是有些犹豫,因为问题来得随机,去得也随机。简而言之,这个问题目前没有答案。现在,问题已经解决了。 - degenPenguin
2个回答

0

拥有这样一个装置:

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的密码,而不是保存到DB表中的password_digest(最终字段)。

Rails将验证那个"fake"或中间密码字段,如果通过,则生成摘要并将密码字段留空。这就是为什么您必须添加allow_blank: true,以便测试可以通过。


0

尝试使用以下代码

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

Bcrypt有一个验证,即在创建新记录时应该存在password attr_accessor更新时可选)。

此外,您应该为密码添加allow_blank: true到您的length validation,因为当密码本身为空/nil时不需要长度验证。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接