【问题标题】:Delayed job with custom attributes具有自定义属性的延迟作业
【发布时间】:2012-04-29 21:35:36
【问题描述】:

我正在使用带有 ActiveRecord 和 Rails 3.2.3 的延迟作业 3.0.2。我有一个使用 has_secure_password 混合的用户模型,因此密码仅以加密方式存储。现在我想使用延迟作业发送欢迎电子邮件,其中应包含未加密密码的副本。

创建记录时,明文密码在User#password中。但是延迟的工作似乎只序列化/反序列化记录的 id 并通过执行 User.find(X) 创建模型的新实例。这样我的纯文本密码就丢失了,用户在他的电子邮件中得到一个空密码。

我如何告诉延迟作业也序列化/反序列化自定义“虚拟”属性,否则这些属性不会存储在数据库中?

这是我用于延迟作业 2.x 的猴子补丁,效果很好。

class ActiveRecord::Base
  def self.yaml_new(klass, tag, val)
    klass.find(val['attributes']['id']).tap do |m|
      val.except("attributes").each_pair{ |k, v| m.send("#{k}=", v) }
    end
  rescue ActiveRecord::RecordNotFound
    raise Delayed::DeserializationError
  end
end

它不适用于延迟作业 3.x。我对修复我的猴子补丁也不是很感兴趣,因为我希望对此有一个适当的解决方案

【问题讨论】:

  • 如果我正确理解了您的帖子,您将通过电子邮件发送纯文本密码。在我看来,在电子邮件中发送纯文本密码是一个安全问题。我不会包括它。有关它的更多信息,请参见此处的最佳答案 (stackoverflow.com/questions/1069722/…)

标签: ruby-on-rails-3 delayed-job


【解决方案1】:

在延迟作业 3.x 中,最好的方法是覆盖 ActiveRecord 类上的一些方法,然后强制 Psych YAML 反序列化器从序列化数据中加载 ActiveRecord 对象。默认情况下,延迟作业仅使用反序列化的 id,然后从数据库加载 ActiveRecord 对象。因此,假设我有一个名为 ShipmentImport 的 ActiveRecord 类,并且我想要一个名为“user_id”的 attr_accessor 来处理延迟的作业序列化/反序列化。这就是我要做的。

在 ShipmentImport ActiveRecord 类中,添加:

def encode_with(coder)
  super
  coder['user_id'] = @user_id
end

def init_with(coder)
 super
  @user_id = coder['user_id']
  self
end

在您的应用程序的初始化程序中,为您的 ActiveRecord 类添加以下内容:

Psych.load_tags[['!ruby/ActiveRecord', ShipmentImport.name].join(':')] = ShipmentImport

【讨论】:

  • 谢谢,这很有帮助!你能解释一下初始化程序的代码在做什么吗?另外,您是否认为这是一个潜在的安全问题——也就是说,这是否可能使外人更容易发现属性的值?
  • 初始化程序代码告诉延迟作业通过实际反序列化序列化对象来初始化对象,而不是仅仅反序列化 id 然后从数据库中查找它。
  • 另外,我没有看到任何本质上不安全的东西,通过增加延迟作业来支持不是数据库字段的属性。应用此技术的具体方式可能会引发安全问题,但几乎所有您编写的代码都是如此。
猜你喜欢
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多