1

Because rails clears the errors during save, I can't do this in my model:

  def password= plain_text
    if plain_text =~ /\d/ && plain_text =~ /\w/
      self.password_digest = BCrypt::Password.create(plain_text)
    else
      self.errors[:password] = "must contain one digit and one word character."
    end
  end

What's the best way to validate a password to have one letter and one digit in rails, while still using bcrypt?

4

1 回答 1

2

如果您使用的是 Railshas_secure_password选项,那么 Rails 将为password=您处理该方法。当您设置密码时,Rails 将保留实例变量中未加密的密码@password

def password=(unencrypted_password)
  ...
  @password = unencrypted_password
  cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
  self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost)

@password值将保留在内存中,直到将记录保存到数据库中。因此,您可以针对password. 验证通过后,password_digest将存储加密值。

您可以看到这是 Rails 在验证密码不超过允许的最大密码时所做的事情:

validates_length_of :password, maximum: ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED
于 2020-01-02T14:18:45.163 回答