2

我想实现一个 RailsUser模型,它有一个名为password. 我想做到这一点,以便当我打电话时......

user_instance.password = 'cleartext'

该方法在将明文设置在实例上之前对其进行哈希处理,如下所示:

Digest::SHA1.hexdigest(cleartext)

我试过使用回调,但问题是每次保存用户时都会对 pw 进行哈希处理,即使 pw 没有更新也是如此。所以它被一遍又一遍地散列和重新散列。

我尝试重新定义password=方法...

alias password= old_password=
def password=(cleartext)
  old_password=(Digest::SHA1.hexdigest(cleartext))
end

但得到一个错误说不password=存在。

4

4 回答 4

8

仅供参考,您可能需要查看 restful_authentication 插件,因为它会为您执行此操作。为什么要自己滚动?

act_as_authenticated 的方式:

  1. 数据库/模型有一个名为“encrypted_pa​​ssword”的列
  2. 创建一个名为密码的虚拟属性
  3. 密码未在 find(..) 上填充,因此如果密码为空,请不要加密
  4. 如果密码是非空的,这意味着用户输入了一个,所以继续加密并在 encrypted_pa​​ssword 中填充

代码片段(从我的用户类中随机复制粘贴,所以不要盲目粘贴):

require 'digest/sha1'
class User < ActiveRecord::Base

  # stuff

  # callback
  before_save   :encrypt_password
  attr_accessor :password

  # methods
    def encrypt_password
      return if password.blank?
      salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
      crypted_password = Digest::SHA1.hexdigest("--#{salt}--#{self.password}--")
    end
于 2009-02-16T21:11:15.650 回答
1

针对 Ethan 的评论,什么是虚拟属性,虚拟属性是不在数据库中的属性,例如 Matt 的 attr_accessor :password,这样您就可以接受来自用户的输入,但不一定以那种形式存储它,在这种情况下,我们希望能够接受明文密码,但我们希望将其加密存储。为此,我们有一个虚拟属性:password,并在数据库中将其存储为 encrypted_pa​​ssword。

于 2009-02-17T01:41:39.650 回答
1

好吧,您可以覆盖设置器:

def password=(value)
  self[:password] = Digest::SHA1.hexdigest(value)
end

总是会加密价值。您不需要 before_saveattr_accessor。

于 2009-02-17T05:06:09.127 回答
1

请注意,为每个用户选择一个随机的 n 位值(在创建该用户时)并在您对其进行哈希处理时将其添加到密码中可能是个好主意。

原因是:如果有人掌握了你的数据库,他们不仅不能立即看到用户的密码,他们也不能看到两个用户是否有相同的密码(如果其中一个用户抓住了你的数据库,这很重要)和某种类型的哈希破解攻击(彩虹表)变得更加困难。

于 2009-02-17T08:24:55.593 回答