Как я могу заставить метод установки шифровать данные перед установкой в ​​ActiveRecord? - PullRequest
2 голосов
/ 17 февраля 2009

Я хотел бы реализовать модель Rails User, в которой столбец БД называется password. Я хочу сделать так, чтобы, когда я звоню ...

user_instance.password = 'cleartext'

метод хеширует открытый текст перед установкой его на экземпляр следующим образом:

Digest::SHA1.hexdigest(cleartext)

Я пытался использовать обратный вызов, но проблема в том, что он хэширует pw при каждом сохранении пользователя, даже если pw не обновляется. Таким образом, он хешируется и перефразируется снова и снова.

Я попытался переопределить метод password= ...

alias password= old_password=
def password=(cleartext)
  old_password=(Digest::SHA1.hexdigest(cleartext))
end

но получил сообщение об ошибке password= не существует.

Ответы [ 4 ]

8 голосов
/ 17 февраля 2009

Между прочим, вы можете проверить плагин restful_authentication, так как он сделает это за вас. Зачем кататься самостоятельно?

Способ, которым действует act_as_authenticated:

  1. База данных / модель имеет столбец с именем «encrypted_password»
  2. Создать виртуальный атрибут с именем password
  3. Пароль не найден при поиске (..), поэтому, если пароль пуст, не шифруйте
  4. Если пароль не является пустым, это означает, что пользователь ввел его, поэтому продолжайте шифровать и вводите шифрованное_пароль

Отрывок кода (случайная копия-вставка из моего пользовательского класса, так что не вставляйте это вслепую):

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

  # stuff

  # callback
  before_save   :encrypt_password
  attr_accessor :password

  # methods
    def encrypt_password
      return if password.blank?
      salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
      crypted_password = Digest::SHA1.hexdigest("--#{salt}--#{self.password}--")
    end
1 голос
/ 17 февраля 2009

Обратите внимание, что было бы неплохо выбрать случайное n-битное значение для каждого пользователя (при создании этого пользователя) и добавить его к паролю, когда вы его хешируете.

Причина в том, что если кто-то завладеет вашей базой данных, они не только не смогут сразу увидеть пароль пользователя, но и не смогут увидеть, имеют ли два пользователя одинаковые пароли (важно, если один из этих пользователей захватит ваш базы данных), и определенный класс хакерских атак (радужных таблиц) становится сложнее.

1 голос
/ 17 февраля 2009

Ну, вы можете переопределить сеттер:

def password=(value)
  self[:password] = Digest::SHA1.hexdigest(value)
end

И это всегда шифрует значение. Тебе не нужен before_save или attr_accessor.

1 голос
/ 17 февраля 2009

В ответ на комментарий Этана о том, что является виртуальным атрибутом, виртуальный атрибут - это атрибут, которого нет в базе данных, как attr_accessor: пароль Мэтта, так что вы можете принять этот ввод от пользователя, но не обязательно хранить его в эта форма, в данном случае мы хотим иметь возможность принимать открытый текстовый пароль, но мы хотим хранить его в зашифрованном виде. Для этого у нас есть виртуальный атрибут: пароль, и в базе данных мы храним его как encrypted_password.

...