在Rails中使用BCrypt手动进行身份验证

时间:2014-07-23 23:01:58

标签: ruby-on-rails ruby bcrypt-ruby

我尝试在我的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,但我想手动实现这一点,以便真正了解正在发生的事情。

1 个答案:

答案 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

它应该按照你的意图工作。