1

Rails アプリで BCrypt を使用して、ユーザーのパスワードを安全に保存しようとしています。暗号化されたパスワードを問題なく保存し、それを元のプレーン テキスト文字列と比較して正常に検証することさえできます。問題は、パスワードを暗号化するたびに異なる出力が得られ (ソルトか何かが原因であると想定しています)、データベースに保存された後に検証が保持されないことです (私は.違いがある場合は sqlite3 データベース)。

例 (Rails コンソール):

2.1.2 :001 > u = User.new
 => #<User id: nil, created_at: nil, updated_at: nil, username: nil, password: nil> 
2.1.2 :002 > u.username = "jdoe"
 => "jdoe"
2.1.2 :002 > u.password = BCrypt::Password.create("snoopy")
 => "$2a$10$jJpHrgUmAh.YULY9CJUDjOSb9audpeD3Hx.66uVhix.WEDDB0HO.y" 
2.1.2 :003 > u.password == "snoopy"
 => true
2.1.2 :004 > u.save
 => true
u2 = User.find_by_username("jdoe")
 => [user "jdoe" is found here]
2.1.2 :006 > u2.password == "snoopy"
 => false

has_secure_password のような既製のソリューションがあることは知っていますが、これを手動で実装して、何が起こっているのかを本当に理解したいと思います。

4

1 に答える 1

1

パスワードを設定すると、BCrypt::Password オブジェクトに設定されます。==データベースからロードすると、単純な文字列としてロードされるため、指定された文字列を元のソルトで暗号化しないと思います。

次のことを試してください。

(...)
u.save
u2 = User.find_by_username("jdoe")
BCrypt::Password.new(u2.password) == "snoopy"

編集

Railsはafter_findコールバックを提供しているようですので、このようなものを定義すると

class User < ActiveRecord::Base
  after_find do |user|
    user.password = BCrypt::Password.new(user.password)
  end
end

意図したとおりに動作するはずです。

于 2014-07-23T23:10:23.963 に答える