2010-05-04 87 views
0

這段代碼來自於使用rails書的敏捷web開發..我不明白代碼的這部分內容... 用戶是一個名稱爲hashed_pa​​ssword,鹽爲字段的模型。但是在代碼中他們提到了密碼和密碼確認,而模型中沒有這樣的字段。模型只有hashed_pa​​ssword。我相信錯誤與我同在。請爲我清除:) 用戶模型有名稱,hashed_pa​​ssword,salt。所有字段都是字符串使用rails的敏捷web開發

require 'digest/sha1' 
class User < ActiveRecord::Base 
     validates_presence_of :name 
     validates_uniqueness_of :name 
     attr_accessor :password_confirmation 
     validates_confirmation_of :password 
     validate :password_non_blank 

     def self.authenticate(name, password) 
      user = self.find_by_name(name) 
      if user 
      expected_password = encrypted_password(password, user.salt)    
      if user.hashed_password != expected_password 
       user = nil 
      end 
      end 
      user 
     end 

     def password 
      @password 
     end 

     def password=(pwd) 
      @password = pwd 
      return if pwd.blank? 
      create_new_salt 
      self.hashed_password = User.encrypted_password(self.password, self.salt) 
     end 

     private 
     def password_non_blank 
      errors.add(:password,"Missing password")if hashed_password.blank? 
     end 

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

     def self.encrypted_password(password, salt) 
      string_to_hash = password + "wibble" + salt 
      Digest::SHA1.hexdigest(string_to_hash) 
     end 
end 

回答

4

attr_accessor用於爲實例變量創建getter/setter方法。例如:

attr_accessor :foo 

# is equivalent to 

def foo 
    @foo 
end 

def foo=(value) 
    @foo = value 
end 

在代碼你粘貼,def passworddef password=手動定義。不過,我有點被利用的困惑:

attr_accessor :password_confirmation 

validates_confirmation_of :foo會自動創建一個foo_confirmation訪問,所以這應該是:

attr_accessor :password 
validates_confirmation_of :password 

添加一個簡單的before_save回調加密的密碼和你全部完成了。

require 'digest/sha1' 
class User < ActiveRecord::Base 

    # attrs 
    attr_accessor :password 

    # class methods 
    class << self 
    def encrypt(password, salt) 
     Digest::SHA1.hexdigest("--#{salt}--#{password}--"); 
    end 
    end 

    # validation 
    validates_presence_of  :name 
    validates_confirmation_of :password 

    # callbacks 
    before_save :encrypt_password 

    protected 

    def encrypt_password 
    return if password.blank? 
    if new_record? 
     self.salt = Digest::SHA1.hexdigest("--#{Time.now}--#{name}--") 
    end 
    self.encrypted_password = User.encrypt(password, salt) 
    end 

end 
3

由於您不希望以明文形式將密碼存儲在數據庫中,因此您將創建一個名爲password的虛擬屬性。當你寫你這樣做:

def password=(pwd) 
    @password = pwd 
    return if pwd.blank? 
    create_new_salt 
    self.hashed_password = User.encrypted_password(self.password, self.salt) 
end 

這樣一來,當你調用密碼=「維布勒」它實際上是加密「維布勒」,並在數據庫中存儲加密的值來代替。

attr_accessor :password_confirmation 

即一條線是相同的,如果你:

+1

謝謝...這部分代碼 attr_accessor:password_confirmation validates_confirmation_of:password – felix 2010-05-04 18:13:50

0

在該示例中,password_confirmation屬性使用attr_accessor中輔助,其設置爲你的吸氣劑和mutator在一行代碼添加到模型中這樣寫的:

def password_confirmation 
    @password_confirmation 
end 

def password_confirmation=(pwd_conf) 
    @password_confirmation = pwd_conf 
end 

密碼的存取在模型中明確定義:

 def password 
      @password 
     end 

     def password=(pwd) 
      @password = pwd 
      return if pwd.blank? 
      create_new_salt 
      self.hashed_password = User.encrypted_password(self.password, self.salt) 
     end 

這些虛擬屬性是在模型代碼中定義的,因爲它們不存在於數據庫表中,模型從其中獲取屬性的其餘部分,因爲您不希望它們存儲在數據庫中。