Rails:如何在不使用has_secure_password的情况下编写自己的身份验证

时间:2013-10-04 04:21:38

标签: validation authentication ruby-on-rails-4

在我的应用中,管理员仅使用电子邮件创建用户。当用户尝试设置密码时,它不起作用。以下代码仅在我删除验证时有效。

def password=(password_str)
  @password = password_str 
  self.password_salt   = BCrypt::Engine.generate_salt
  self.password_digest = BCrypt::Engine.hash_secret(password_str, password_salt)
end

def authenticate(password)
  password.present? && password_digest.present? && password_digest == BCrypt::Engine.hash_secret(password, password_salt)
end

validates :password             , length: { minimum: 6 }, :if => :setting_password?
validates :password_confirmation, presence: true        , :if => :setting_password?

def setting_password?
 self.password || self.password_confirmation
end

1)只有在我对密码

进行评论时才能设置密码

2)password_confirmation字段保存密码..

2 个答案:

答案 0 :(得分:3)

对于大多数类型的身份验证(以及我大部分时间都使用的身份验证),这是一个有用的解决方案,但如果你真的需要在没有has_secure_password的情况下编写身份验证,Ryan Bates的Railscasts有got you covered

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation

  attr_accessor :password
  before_save :encrypt_password

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email

  def self.authenticate(email, password)
    user = find_by_email(email)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end
end

for rails 4这是不同的(模型上没有更多的attr_accessors),修改它我们需要一个attr_reader:password以及一种设置密码和password_confirmation的方法:

class User < ActiveRecord::Base
  attr_reader :password
  before_save :encrypt_password

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email

  def self.authenticate(email, password)
    user = find_by_email(email)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end

  ##
  # accessor
  def password=(unencrypted_password)
    unless unencrypted_password.blank?
      @password = unencrypted_password
    end
  end

  ##
  # accessor
  def password_confirmation=(unencrypted_password)
    @password_confirmation = unencrypted_password
  end
end

但是,如果我们查看has_secure_password方法here,我们会看到业务逻辑在密码=(未加密)而不是之前的保存回调(这显然是有道理的)我觉得这可能是最干净的执行此方法。

答案 1 :(得分:2)

嘿结帐rails 4教程这里可能会给你一些想法。 http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#cha-modeling_users

通过bcrypt进行用户身份验证。