我尝试在我的rails应用中使用BCrypt来安全地保存用户的密码。我能够很好地保存加密密码,甚至可以将其与原始纯文本字符串进行比较,以便成功验证它。问题似乎是每次我加密密码时我得到一个不同的输出(我假设由于某些盐或其他东西)并且验证在保存到数据库后不会停滞(I&# 39;如果它有所不同,则保存在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,但我想手动实现这一点,以便真正了解正在发生的事情。
答案 0 :(得分: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
它应该按照你的意图工作。