跳至内容 跳至搜索

Active Record 签名 ID

命名空间
方法
S

类公共方法

signed_id_verifier_secret

在 Rails 之外使用 Active Record 时,设置用于签名 ID 验证器实例的密钥。在 Rails 中,这将使用 Rails 应用程序密钥生成器自动设置。

# File activerecord/lib/active_record/signed_id.rb, line 13
class_attribute :signed_id_verifier_secret, instance_writer: false

实例公共方法

signed_id(expires_in: nil, expires_at: nil, purpose: nil)

返回使用预先配置的 ActiveSupport::MessageVerifier 实例生成的签名 ID。

此签名 ID 是防篡改的,因此可以安全地发送到电子邮件或与外部世界共享。但是,与使用 ActiveSupport::MessageVerifier 签名的任何消息一样,签名 ID 未加密。它只是编码并防止被篡改。

这意味着任何人都可以解码 ID;但是,如果被篡改(指向另一个 ID),加密签名将不再匹配,并且签名 ID 将被视为无效,并在传递给 find_signed 时返回 nil(或使用 find_signed! 抛出异常)。

此外,它可以设置为过期(默认情况下不过期),并且可以使用特定目的进行范围缩小。如果在调用 find_signed 之前已超过过期日期,则 ID 将无法找到指定的记录。如果设置了目的,则它也必须匹配。

如果您不小心将签名 ID 泄露到野外,并且希望在过期日期之前撤回它(或者您忘记设置过期日期,而实际上应该设置),您可以使用目的来实质上对 signed_id 进行版本控制,如下所示

user.signed_id purpose: :v2

然后,您将 find_signed 调用更改为要求此新目的。任何没有使用此目的创建的旧签名 ID 将不再找到记录。

# File activerecord/lib/active_record/signed_id.rb, line 131
def signed_id(expires_in: nil, expires_at: nil, purpose: nil)
  raise ArgumentError, "Cannot get a signed_id for a new record" if new_record?

  self.class.signed_id_verifier.generate id, expires_in: expires_in, expires_at: expires_at, purpose: self.class.combine_signed_id_purposes(purpose)
end