1

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

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 字段按原样保存密码..

4

2 回答 2

3

对于大多数类型的身份验证(以及我大部分时间使用的身份验证)来说,这是一个有用的解决方案,但是如果您真的需要在没有 has_secure_password 的情况下编写身份验证,Ryan Bates 的 Railscasts 已经为提供了保障。

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

对于 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 方法,我们会发现业务逻辑在 password=(unencrypted) 中,而不是在保存前的回调中(这很明显)我觉得这可能是执行此操作的最干净的方法。

于 2013-11-11T14:09:14.637 回答
2

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

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

于 2013-10-04T11:46:47.160 回答