Придумайте: вручную шифруйте пароль и храните непосредственно
Я пытаюсь перенести тонну пользователей из старой базы данных. Для этого я использую activerecord-import и пытаюсь сохранить все свои пользовательские данные непосредственно в DB (минуя модель User).
Моя проблема: мне нужно взять старый пользовательский текстовый пароль, зашифровать его и сохранить непосредственно в БД. Я знаю, как сгенерировать пароль с помощью Devise, но мне интересно, есть ли способ получить хешированный пароль, который я могу хранить непосредственно в базе данных.
В надежде сделать:
new_hashed_password = Devise.awesome_encrypting_method(old_user.password)
Затем сохраните "new_hashed_password" непосредственно в БД без прохождения модели. Я выкопался в Devise и нашел это:
def password_digest(password)
::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
end
@@растягивает по умолчанию 10 (lib/devise.rb: 71) и не переопределяется моим инициализатором
@@pepper по умолчанию nil (lib/devise.rb: 148) и не переопределяется моим инициализатором
Я думал, что могу вручную создать пароль password_digest(), но я думаю, что мне не хватает чего-то фундаментального в Bcrypt, потому что даже при установке пароля и растяжек результирующий хеш каждый раз отличается.
Любые идеи? Спасибо за вашу помощь!
Ответы
Ответ 1
Хорошие новости и плохие новости.
Хорошие новости:
Ниже описано, как создать пароль пользователя вручную.
pepper = nil
cost = 10
encrypted_password = ::BCrypt::Password.create("#{password}#{pepper}", :cost => cost).to_s
Вы можете найти свой перец и стоимость в инициализаторе вашего проекта. Этот метод был подтвержден с помощью Devise "valid_password?" Метод.
Плохая новость:
Вся причина, по которой я пытался избежать "User.new(пароль: пароль).encrypted_password", был из-за скорости. Это ужасно медленно. Со всеми моими другими частями моей задачи импорта я намеренно избегал этого.
Но, как выясняется, главная стоимость здесь не создает экземпляр объекта User, а сам BCrypt. При использовании BCrypt очень мало заметного повышения скорости, потому что он намеренно предназначен для медленного.
Мой окончательный ответ: сосать его, запустить rake script, пойти найти напиток.
Ответ 2
Вы должны сделать это следующим образом:
password = 'the secret password'
new_hashed_password = User.new(:password => password).encrypted_password
Это намного лучше, чем использование BCrypt напрямую, поскольку оно абстрагирует, как генерируются пароли из вашего кода, что упрощает его понимание, а также невосприимчивость к изменениям в том, как devits строит зашифрованные пароли. Ваш код не должен и не должен знать об этом.
Ответ 3
Альтернативный метод: User.new.send(:password_digest, 'xxx')
Ответ 4
Предполагая, что у вас есть база данных mysql с таблицей "пользователи" и столбцом "пароль"
И класс модели ActiveRecord, называемый "пользователь", который подключен к разработке
Создайте класс модели ActiveRecord в своем приложении
приложение/модели/old_user.rb
OldUser < ActiveRecord::Base
set_table :users
establish_connection :database => "old_database", :user => "old user", :adapter => "mysql"
end
затем создайте задачу грабли:
Приложение/Library/задачи/migrate_users.rake
task :migrate_users => :environment do
OldUser.find_each do |old_user|
u = User.new(:email => old_user.email, :password => old_user.password, :password_confirmation => old_user.password);
#if your using confirmation
u.skip_confirmation!
u.save!
end
end
Измените при необходимости (убедитесь, что вы сохраняете атрибуты пользовательских приложений)
Тогда $ rake migrate_users
Ответ 5
Ни один из других ответов выше не работал у меня, поэтому вот что я сделал:
user.valid_password?(plain_password)
https://github.com/plataformatec/devise/blob/d293e00ef5f431129108c1cbebe942b32e6ba616/lib/devise/models/database_authenticatable.rb#L44