Я начал работать над проектом, в котором уже было много кода. Это приложение Ruby on Rail, которое использует Devise для аутентификации пользователей. Одним из требований приложения является то, что когда пользователь меняет свой пароль, ему не разрешается использовать тот же пароль, что и последние три пароля, которые он использовал ранее. Для этого есть таблица, которая содержит историю паролей для данного пользователя. Эти пароли являются копиями зашифрованных паролей, которые существовали до любой смены пароля пользователем.
Здесь возникает проблема. У нас есть форма смены пароля, которая собирает новый пароль для данного пользователя. Мне нужно иметь возможность взять новый пароль и зашифровать его, чтобы я мог сопоставить зашифрованное значение нового пароля с зашифрованными значениями старых паролей в истории.
Технический материал
Rails версия 3.0.9
Разработать версию 1.3.4
Используя стандартный BCrypt с Devise. bcrypt_ruby версия 2.1.4
Для этого мы переопределяем метод reset_password, поддерживаемый Devise. Это позволяет нам представить наш собственный метод has_repeated_password в пользовательском контроллере.
Ниже приведена версия has_repeated_password, с которой я начал:
def has_repeated_password?
return false if self.new_record? || self.version == 1
histories = self.versions.find(:all, :order => 'version DESC', :limit => 3)
histories.detect do |history|
history.encrypted_password == self.class.encryptor_class.digest(self.password, self.class.stretches, history.password_salt, self.class.pepper)
end
end
Проблема здесь в том, что класс encryptor никогда не определяется, вызывая ошибку при каждом запуске этой подпрограммы. Даже несмотря на то, что есть много примеров, которые утверждают, что это работает, я не могу заставить его работать, когда Devise использует шифрование по умолчанию.
Вторая попытка это следующий код:
def has_repeated_password?<br>
return false if self.new_record? || self.version == 1
histories = self.versions.find(:all, :order => 'version DESC', :limit => 3)
histories.detect do |history|
pwd = self.password_digest(self.password)
history.encrypted_password == pwd
end
end
В этом случае я никогда не получу пароль, который соответствует какому-либо из сохраненных паролей, хотя я и подтвердил, что пароль в базе данных - это то, что я ожидаю.
Я пытался покопаться в коде Devise, чтобы посмотреть, что я там найду. Я знаю, что аутентификация должна делать это как-то, когда она сопоставляет пароли, собранные у пользователей, с сохраненным паролем.
Любая помощь будет оценена.