rails关于user密码hash的重构

rails应用程序中一个model名为User,其中存放了用户名和对应的密码.User模式类中建立了1个虚拟属性password用来存放用户实际输入的密码;而最终数据库的密码需要计算password的散列后再存入,此外计算散列需要一个salt作为种子,该种子是随机生成的,生成后也保存在数据库中:

def generate_salt
 self.salt = self.object_id.to_s + rand.to_s
end

模式User中需要验证用户输入各项的正确性,包括用户名不能为空,密码不能为空,两次输入的密码必须相同:

validates :name,presence:true,uniqueness:true
validates :password,confirmation:true
attr_accessor :password_confirmation
attr_reader :password

validate :password_must_be_present

def password_must_be_present
 errors.add(:password,'Missing password') unless hashed_password.present?
end

其中单独写出password=的方法,在password被赋值时,计算salt和password哈希的值:

def self.encrypt_password(password,salt)
    Digest::SHA2.hexdigest(password + "wibble" + salt)
  end

#password is a virtual attribute
  def password=(password)
    @password = password

    #An object is present if it's not blank,mean:
    # 1.present? => true
    # "".present? => false
    # "hi".present? => true
    if password.present?
      generate_salt
      self.hashed_password = self.class.encrypt_password(password,salt)
    end
  end

现在将以上功能重构,将计算salt和password哈希的代码放在model回调钩子before_save中,并将password_must_be_present删掉,加上

  validates :password,presence:true

删除password=方法,并修改password属性为:

  attr_accessor :password

然后新增before_save钩子:

  before_save :calc_hash
  def calc_hash
    if self.password.present?
      generate_salt
      self.hashed_password = self.class.encrypt_password(password,salt)
    end
  end

在写回调函数的时候发现用:

class User
  def before_save
  end
end

方式写的钩子无法被回调,一定要用before_save的方式吗? :(

上一篇:JS之正则表达式验证URL


下一篇:C语言 goto语句