Разработать: вручную зашифровать пароль и сохранить напрямую - PullRequest
32 голосов
/ 05 ноября 2011

Я пытаюсь перенести тонну пользователей из старой базы данных. Для этого я использую activerecord-import и пытаюсь сохранить все свои пользовательские данные непосредственно в БД (в обход модели 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, потому что даже с установкой пароля и растяжений результирующий хэш каждый раз отличается.

Есть идеи? Спасибо за вашу помощь!

Ответы [ 5 ]

58 голосов
/ 02 июля 2013

Вы должны сделать это так:

password = 'the secret password'
new_hashed_password = User.new(:password => password).encrypted_password

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

19 голосов
/ 05 ноября 2011

Хорошие новости и плохие новости.

Хорошие новости:

Следующее работает для создания пароля пользователя вручную.

 pepper = nil
 cost = 10
 encrypted_password = ::BCrypt::Password.create("#{password}#{pepper}", :cost => cost).to_s

Вы можете найти свой перец и стоимостьв вашем устройстве инициализатора.Этот метод был подтвержден с помощью Devise "valid_password?"method.

Плохие новости:

Причина, по которой я пытался избежать "User.new (пароль: пароль) .encrypted_password", была из-за скорости.Это ужасно медленно.Со всеми другими частями моей задачи по импорту я намеренно избегал этого.

Но, как выясняется, основные затраты здесь заключаются не в создании экземпляра объекта User, а в самом BCrypt.При прямом использовании BCrypt очень мало заметного прироста скорости, потому что он намеренно разработан, чтобы быть медленным.

Мой окончательный ответ: смиритесь с этим, запустите скрипт рейка, иди и найдите напиток.

3 голосов
/ 11 августа 2016

Ни один из приведенных выше ответов не сработал для меня, поэтому вот что я сделал:

user.valid_password?(plain_password)

https://github.com/plataformatec/devise/blob/d293e00ef5f431129108c1cbebe942b32e6ba616/lib/devise/models/database_authenticatable.rb#L44

2 голосов
/ 10 августа 2013

Альтернативный метод: User.new.send(:password_digest, 'xxx')

1 голос
/ 05 ноября 2011

Предполагается, что у вас есть база данных mysql с таблицей «users» и столбцом «password» И класс модели ActiveRecord, называемый «пользователь», который подключен для разработки

Создание класса модели ActiveRecord в вашем приложении приложение / модели / old_user.rb

OldUser < ActiveRecord::Base
  set_table :users
  establish_connection :database => "old_database", :user => "old user", :adapter => "mysql"
end

затем создайте грабли: Приложение / Библиотека / Задачи / 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

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