跳至内容 跳至搜索
方法
A

实例公有方法

authenticate_by(attributes)

给定一组属性,使用非密码属性查找记录,然后使用密码属性对该记录进行身份验证。如果身份验证成功,则返回记录;否则,返回 nil

无论是否找到记录,authenticate_by 都将对给定的密码属性进行密码学摘要。此行为有助于减轻基于时间的枚举攻击,攻击者在其中可以确定是否存在密码记录,即使他们不知道密码。

如果属性集至少不包含一个密码和一个非密码属性,则会引发 ArgumentError。

示例

class User < ActiveRecord::Base
  has_secure_password
end

User.create(name: "John Doe", email: "[email protected]", password: "abc123")

User.authenticate_by(email: "[email protected]", password: "abc123").name # => "John Doe" (in 373.4ms)
User.authenticate_by(email: "[email protected]", password: "wrong")       # => nil (in 373.9ms)
User.authenticate_by(email: "[email protected]", password: "abc123")     # => nil (in 373.6ms)

User.authenticate_by(email: "[email protected]", password: nil) # => nil (no queries executed)
User.authenticate_by(email: "[email protected]", password: "")  # => nil (no queries executed)

User.authenticate_by(email: "[email protected]") # => ArgumentError
User.authenticate_by(password: "abc123")        # => ArgumentError
# File activerecord/lib/active_record/secure_password.rb, line 41
def authenticate_by(attributes)
  passwords, identifiers = attributes.to_h.partition do |name, value|
    !has_attribute?(name) && has_attribute?("#{name}_digest")
  end.map(&:to_h)

  raise ArgumentError, "One or more password arguments are required" if passwords.empty?
  raise ArgumentError, "One or more finder arguments are required" if identifiers.empty?

  return if passwords.any? { |name, value| value.nil? || value.empty? }

  if record = find_by(identifiers)
    record if passwords.count { |name, value| record.public_send(:"authenticate_#{name}", value) } == passwords.size
  else
    new(passwords)
    nil
  end
end