Гибкая веб-разработка с рельсами - PullRequest
0 голосов
/ 04 мая 2010

Этот код взят из книги по гибкой веб-разработке с rails. Я не понимаю эту часть кода ... Пользователь - это модель, в которой в качестве полей указаны имя, hashed_password, salt.Но в коде упоминается о пароле и подтверждении пароля, а в модели таких полей нет.Модель имеет только hashed_password.Я уверен, что ошибка со мной.Пожалуйста, очистите это для меня :) У модели пользователя есть имя, hashed_password, соль.Все поля являются строками

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 ]

4 голосов
/ 04 мая 2010

attr_accessor используется для создания методов получения / установки для переменной экземпляра. Например:

attr_accessor :foo

# is equivalent to

def foo
  @foo
end

def foo=(value)
  @foo = value
end

В вставленном вами коде def password и def 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 голосов
/ 04 мая 2010

Поскольку вы не хотите хранить пароль в базе данных в виде открытого текста, вы создаете виртуальный атрибут с именем password. Вы делаете это, когда пишете:

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

Таким образом, когда вы вызываете password = "wibble", он фактически шифрует "wibble" и вместо этого сохраняет зашифрованное значение в базе данных.

0 голосов
/ 30 апреля 2011

У меня был тот же вопрос.

Мне показался полезным элемент validates_confirmation_of на сайте Rails API: http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000081.

0 голосов
/ 04 мая 2010

В этом примере свойство password_confirmation добавляется в модель с помощью помощника attr_accessor, который устанавливает для вас геттер и мутатор в одной строке кода:

attr_accessor :password_confirmation

Эта строка такая же, как если бы вы написали это:

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

Эти виртуальные атрибуты определены в коде модели, поскольку они не существуют в таблице базы данных, из которой модель получает остальные свои атрибуты, потому что вы не хотите, чтобы они сохранялись в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...