модуль ActiveRecord::SignedId::ClassMethods
Общедоступные методы экземпляров
# File activerecord/lib/active_record/signed_id.rb, line 42
def find_signed(signed_id, purpose: nil)
raise UnknownPrimaryKey.new(self) if primary_key.nil?
if id = signed_id_verifier.verified(signed_id, purpose: combine_signed_id_purposes(purpose))
find_by primary_key => id
end
end Позволяет найти запись по подписанному идентификатору, который безопасно можно передавать без риска подделки. Это особенно полезно для таких операций, как сброс пароля или подтверждение электронной почты, где у получателя подписанного идентификатора есть возможность взаимодействовать с базовой записью, но обычно только в течение определенного периода времени.
Период действия подписанного идентификатора задаётся во время его генерации с помощью метода экземпляра signed_id(expires_in: 15.minutes). Если время действия истекло до попытки поиска по подписанному идентификатору, подписанный идентификатор больше не будет действительным, и будет возвращено значение nil.
Можно дополнительно ограничить использование подписанного идентификатора с помощью назначения цели. Это полезно, когда у вас есть базовая модель, например, модель пользователя, которая может иметь подписанные идентификаторы для нескольких целей, таких как сброс пароля или подтверждение электронной почты. Цель, заданная во время генерации, должна совпадать с целью, заданной при поиске. Если есть несоответствие, снова возвращается значение nil.
Примеры
signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset User.find_signed signed_id # => nil, since the purpose does not match travel 16.minutes User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired travel_back User.find_signed signed_id, purpose: :password_reset # => User.first
# File activerecord/lib/active_record/signed_id.rb, line 62
def find_signed!(signed_id, purpose: nil)
if id = signed_id_verifier.verify(signed_id, purpose: combine_signed_id_purposes(purpose))
find(id)
end
end Действует как find_signed, но при этом вызовет исключение ActiveSupport::MessageVerifier::InvalidSignature если подписанный идентификатор либо истек, либо имеет несовпадающую цель, либо относится к другой записи, либо был изменён. Также будет выброшено исключение ActiveRecord::RecordNotFound если по валидному подписанному идентификатору не удалось найти запись.
Примеры
User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature signed_id = User.first.signed_id User.first.destroy User.find_signed! signed_id # => ActiveRecord::RecordNotFound
# File activerecord/lib/active_record/signed_id.rb, line 71
def signed_id_verifier
@signed_id_verifier ||= begin
secret = signed_id_verifier_secret
secret = secret.call if secret.respond_to?(:call)
if secret.nil?
raise ArgumentError, "You must set ActiveRecord::Base.signed_id_verifier_secret to use signed ids"
else
ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON
end
end
end Экземпляр верификатора, от которого генерируются и проверяются все подписанные идентификаторы. По умолчанию он инициализируется с помощью класса signed_id_verifier_secret, который в Rails берётся из Rails.application.key_generator. По умолчанию используется SHA256 для хэширования и JSON для сериализации.
# File activerecord/lib/active_record/signed_id.rb, line 87 def signed_id_verifier=(verifier) @signed_id_verifier = verifier end
Позволяет передать настраиваемый верификатор, используемый для подписанных идентификаторов. Это также позволяет использовать разные верификаторы для разных классов. Это также полезно, если необходимо вращать ключи, так как можно заранее подготовить настраиваемый верификатор для этого. Подробнее см. ActiveSupport::MessageVerifier.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.