设计:手动加密密码并直接存储

时间:2011-11-04 21:10:04

标签: ruby-on-rails devise

我正在尝试从旧数据库迁移大量用户。为此,我使用activerecord-import并尝试将所有用户数据直接保存到DB(绕过用户模型)。

我的问题:我需要使用旧用户的纯文本密码,对其进行加密,然后直接存储到数据库中。我知道如何使用Devise 生成密码,但我想知道是否有办法获得可以直接存储到数据库的哈希密码。

希望这样做:

new_hashed_password = Devise.awesome_encrypting_method(old_user.password)

然后将“new_hashed_pa​​ssword”直接存储到数据库中,而无需通过模型。我在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 个答案:

答案 0 :(得分:58)

你应该这样做:

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

这比直接使用BCrypt要好得多,因为它抽象了代码生成密码的方式,使其更易于理解,并且不受设计加密密码设置方式的影响。您的代码不应该,也没有理由知道任何相关内容。

答案 1 :(得分:19)

好消息和坏消息。

好消息:

以下内容适用于手动创建用户密码。

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

您可以在设计初始化程序中找到您的辣椒和成本。使用Devise的“valid_password?”确认了这个方法。方法

坏消息:

我试图避免“User.new(密码:密码).encrypted_pa​​ssword”的全部原因是因为速度。这非常慢。在我的所有其他部分导入任务中,我故意避免这种情况。

但事实证明,这里的主要成本不是实例化User对象 - 而是BCrypt本身。直接使用BCrypt时,速度提升非常小,因为它的设计速度很慢。

我的最终答案:吮吸它,运行rake脚本,去寻找饮料。

答案 2 :(得分:3)

上述其他答案都没有对我有用,所以这就是我所做的:

user.valid_password?(plain_password)

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

答案 3 :(得分:2)

另一种方法是:User.new.send(:password_digest, 'xxx')

答案 4 :(得分:1)

假设您有一个带有“users”表和“password”列的mysql数据库 还有一个名为“user”的ActiveRecord模型类,它连接起来设计

在您的应用中创建ActiveRecord模型类 应用/模型/ old_user.rb

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

然后创建一个rake任务: 应用程序/ LIB /任务/ 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