Преобразование существующего хеша пароля для разработки
Я пытаюсь преобразовать существующую модель администратора в Devise. У нас уже есть хеш-пароль, но он явно не совместим с Devise. Я хотел бы принять форму входа и проверить предоставленный пароль на зашифрованный пароль. Если это неверно, используйте старый хеш, чтобы проверить пароль, и если он соответствует, запустите старое поле password_hash и установите пароль разработчика на предоставленный пароль и сохраните модель.
Какой лучший способ двигаться вперед? Я подозреваю, что мне нужно что-то переопределить, возможно, в пользовательском контроллере, но я не совсем уверен, как действовать дальше.
Ответы
Ответ 1
Вы можете позволить Devise выполнить "тяжелую работу" шифрования пароля с помощью новой схемы склепа, как показано в https://gist.github.com/1704632:
class User < ActiveRecord::Base
alias :devise_valid_password? :valid_password?
def valid_password?(password)
begin
super(password)
rescue BCrypt::Errors::InvalidHash
return false unless Digest::SHA1.hexdigest(password) == encrypted_password
logger.info "User #{email} is using the old password hashing method, updating attribute."
self.password = password
true
end
end
end
Ответ 2
Используя шифр bcrypt в Devise, это то, что я закончил с моими устаревшими данными:
В моделях /user.rb
# Because we have some old legacy users in the database, we need to override Devises method for checking if a password is valid.
# We first ask Devise if the password is valid, and if it throws an InvalidHash exception, we know that we're dealing with a
# legacy user, so we check the password against the SHA1 algorithm that was used to hash the password in the old database.
alias :devise_valid_password? :valid_password?
def valid_password?(password)
begin
devise_valid_password?(password)
rescue BCrypt::Errors::InvalidHash
Digest::SHA1.hexdigest(password) == encrypted_password
end
end
Как вы можете видеть, devise выдает исключение InvalidHash, когда он встречает недопустимый хеш, который он будет делать при аутентификации устаревшего пользователя.
Я использую это, чтобы вернуться к алгоритму хеширования, используемому для создания исходного хэш файла.
Он не изменяет пароль, но может быть просто добавлен в метод, если это необходимо.
Ответ 3
Сначала вам нужно скопировать пароль_salt и encrypted_password в вашу новую объектную модель.
Используя это, потому что я должен экспортировать мою базу данных Пользователь в другое приложение и старый,
приложение использует devise 1.0.x и новое приложение, использующее 2.1.x
Class User < ActiveRecord::Base
alias :devise_valid_password? :valid_password?
def valid_password?(password)
begin
devise_valid_password?(password)
rescue BCrypt::Errors::InvalidHash
salt = password_salt
digest = nil
10.times { digest = ::Digest::SHA1.hexdigest('--' << [salt, digest, password, nil].flatten.join('--') << '--') }
digest
return false unless digest == encrypted_password
logger.info "User #{email} is using the old password hashing method, updating attribute."
self.password = password
self.password_salt = nil # With this you will knew what object already using the new authentication by devise
self.save
true
end
end
end
Ответ 4
Если вы переходите от SHA512, решение немного больше, чем решение moeffju SHA1:
def valid_password?(password)
if has_legacy_password?
return false unless valid_legacy_password?(password)
convert_legacy_password!(password)
true
else
super(password)
end
end
protected
def has_legacy_password?
password_salt.present?
end
def convert_legacy_password!(password)
self.password = password
self.password_salt = nil
self.save
end
def valid_legacy_password?(password)
stretches = 10
salt = password_salt
pepper = nil
digest = pepper
stretches.times do
tokens = [salt, digest, password, pepper]
digest = Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
end
Devise.secure_compare(encrypted_password, digest)
end
Обязательно замените stretches
и pepper
значениями, которые вы использовали для шифрования паролей.
Ответ 5
Следуйте инструкциям Thomas Dippel, которые я сделал, чтобы обновить пароль:
https://gist.github.com/1578362
# Because we have some old legacy users in the database, we need to override Devises method for checking if a password is valid.
# We first ask Devise if the password is valid, and if it throws an InvalidHash exception, we know that we're dealing with a
# legacy user, so we check the password against the SHA1 algorithm that was used to hash the password in the old database.
#SOURCES OF SOLUTION:
# http://stackoverflow.com/info/6113375/converting-existing-password-hash-to-devise
# https://github.com/binarylogic/authlogic/blob/master/lib/authlogic/crypto_providers/sha512.rb
# https://github.com/plataformatec/devise/blob/master/lib/devise/encryptors/authlogic_sha512.rb
alias :devise_valid_password? :valid_password?
def valid_password?(password)
debugger
begin
devise_valid_password?(password)
rescue BCrypt::Errors::InvalidHash
stretches = 20
digest = [password, self.password_salt].flatten.join('')
stretches.times {digest = Digest::SHA512.hexdigest(digest)}
if digest == self.encrypted_password
#Here update old Authlogic SHA512 Password with new Devise ByCrypt password
# SOURCE: https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb
# Digests the password using bcrypt.
# Default strategy for Devise is BCrypt
# def password_digest(password)
# ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
# end
self.encrypted_password = self.password_digest(password)
self.save
return true
else
# If not BCryt password and not old Authlogic SHA512 password Dosn't my user
return false
end
end
end