Ruby on Rails 5.2 - ActiveSupport::MessageVerifier

कक्षा ActiveSupport :: MessageVerifier




ruby

कक्षा ActiveSupport :: MessageVerifier

जनक:
Object

MessageVerifier संदेशों को उत्पन्न करना और सत्यापित करना आसान बनाता है जो छेड़छाड़ को रोकने के लिए हस्ताक्षरित हैं।

यह याद रखने वाले टोकन और ऑटो-सदस्यता समाप्त लिंक जैसे मामलों के लिए उपयोगी है, जहां सत्र स्टोर उपयुक्त या उपलब्ध नहीं है।

मुझे याद रखना:

cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])

प्रमाणीकरण फ़िल्टर में:

id, time = @verifier.verify(cookies[:remember_me])
if Time.now < time
  self.current_user = User.find(id)
end

डिफ़ॉल्ट रूप से यह संदेश को प्रसारित करने के लिए मार्शल का उपयोग करता है। यदि आप एक और क्रमांकन विधि का उपयोग करना चाहते हैं, तो आप आरंभीकरण पर विकल्प हैश में क्रमिक सेट कर सकते हैं:

@verifier = ActiveSupport::MessageVerifier.new('s3Krit', serializer: YAML)

MessageVerifier डिफ़ॉल्ट रूप से SHA1 हैश एल्गोरिथ्म का उपयोग करके HMAC हस्ताक्षर बनाता है। यदि आप एक अलग हैश एल्गोरिथ्म का उपयोग करना चाहते हैं, तो आप इसे प्रदान करके इसे बदल सकते हैं :digest सत्यापनकर्ता को प्रारंभ करते समय एक विकल्प के रूप में कुंजी पचाएं:

@verifier = ActiveSupport::MessageVerifier.new('s3Krit', digest: 'SHA256')

संदेशों को एक विशिष्ट उद्देश्य तक सीमित करना

डिफ़ॉल्ट रूप से किसी भी संदेश का उपयोग आपके ऐप में किया जा सकता है। लेकिन उन्हें एक विशिष्ट :purpose तक ही सीमित रखा जा सकता है।

token = @verifier.generate("this is the chair", purpose: :login)

तब डेटा वापस पाने के लिए सत्यापन करते समय उसी उद्देश्य को पारित किया जाना चाहिए:

@verifier.verified(token, purpose: :login)    # => "this is the chair"
@verifier.verified(token, purpose: :shipping) # => nil
@verifier.verified(token)                     # => nil

@verifier.verify(token, purpose: :login)      # => "this is the chair"
@verifier.verify(token, purpose: :shipping)   # => ActiveSupport::MessageVerifier::InvalidSignature
@verifier.verify(token)                       # => ActiveSupport::MessageVerifier::InvalidSignature

इसी तरह, यदि किसी संदेश का कोई उद्देश्य नहीं है, तो उसे किसी विशिष्ट उद्देश्य के साथ सत्यापित करने पर वापस नहीं किया जाएगा।

token = @verifier.generate("the conversation is lively")
@verifier.verified(token, purpose: :scare_tactics) # => nil
@verifier.verified(token)                          # => "the conversation is lively"

@verifier.verify(token, purpose: :scare_tactics)   # => ActiveSupport::MessageVerifier::InvalidSignature
@verifier.verify(token)                            # => "the conversation is lively"

संदेशों को समाप्त करना

डिफ़ॉल्ट संदेश पिछले हमेशा के लिए और अब से एक वर्ष का सत्यापन करने के बाद भी मूल मूल्य वापस आ जाएगा। लेकिन संदेशों को निश्चित समय के साथ समाप्त होने के लिए सेट किया जा सकता है :expires_in या :expires_at

@verifier.generate(parcel, expires_in: 1.month)
@verifier.generate(doowad, expires_at: Time.now.end_of_year)

तब संदेशों को सत्यापित किया जा सकता है और समय समाप्त हो सकता है। इसके बाद, verified विधि ActiveSupport::MessageVerifier::InvalidSignature रिटर्न करती है जबकि ActiveSupport::MessageVerifier::InvalidSignature

घूमती हुई चाबी

MessageVerifier भी पुराने कॉन्फ़िगरेशन को घूर्णन करने का समर्थन करता है, सत्यापनकर्ताओं के ढेर पर वापस गिरने से। कॉल rotate टू बिल्ड एंड वेरिफ़ायर टू वेरिफायर तो या तो verified या verify भी फ़ॉलबैक के साथ वेरिफ़ाइ करने की कोशिश करेगा।

डिफ़ॉल्ट रूप से कोई भी घुमा हुआ सत्यापनकर्ता प्राथमिक सत्यापनकर्ता के मूल्यों का उपयोग करता है जब तक कि अन्यथा निर्दिष्ट न हो।

आप अपने सत्यापनकर्ता को नई चूक देंगे:

verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512", serializer: JSON)

फिर धीरे-धीरे पुराने मूल्यों को फॉलबैक के रूप में जोड़कर बाहर घुमाएं। पुराने मूल्यों के साथ उत्पन्न कोई भी संदेश तब तक काम करेगा जब तक कि रोटेशन को हटा नहीं दिया जाता।

verifier.rotate old_secret          # Fallback to an old secret instead of @secret.
verifier.rotate digest: "SHA256"    # Fallback to an old digest instead of SHA512.
verifier.rotate serializer: Marshal # Fallback to an old serializer instead of JSON.

हालांकि उपरोक्त सबसे अधिक संभावना एक रोटेशन में जोड़ा जाएगा:

verifier.rotate old_secret, digest: "SHA256", serializer: Marshal

पब्लिक क्लास के तरीके

नया (गुप्त, विकल्प = {}) स्रोत दिखाएं
# File activesupport/lib/active_support/message_verifier.rb, line 106
def initialize(secret, options = {})
  raise ArgumentError, "Secret should not be nil." unless secret
  @secret = secret
  @digest = options[:digest] || "SHA1"
  @serializer = options[:serializer] || Marshal
end

सार्वजनिक प्रवृत्ति के तरीके

उत्पन्न (मान, expires_at: nil, expires_in: nil, उद्देश्य: nil) स्रोत दिखाएं
# File activesupport/lib/active_support/message_verifier.rb, line 186
def generate(value, expires_at: nil, expires_in: nil, purpose: nil)
  data = encode(Messages::Metadata.wrap(@serializer.dump(value), expires_at: expires_at, expires_in: expires_in, purpose: purpose))
  "#{data}--#{generate_digest(data)}"
end

प्रदान किए गए मूल्य के लिए एक हस्ताक्षरित संदेश बनाता है।

संदेश के संदेश हस्ताक्षरकर्ता के रहस्य के साथ हस्ताक्षरित है। रहस्य जाने बिना, मूल मूल्य संदेश से नहीं निकाला जा सकता है।

verifier = ActiveSupport::MessageVerifier.new 's3Krit'
verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
valid_message? (हस्ताक्षरित_माँज) स्रोत दिखाएँ
# File activesupport/lib/active_support/message_verifier.rb, line 122
def valid_message?(signed_message)
  return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.blank?

  data, digest = signed_message.split("--".freeze)
  data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
end

जाँचता है कि क्या एक हस्ताक्षरित संदेश किसी ऑब्जेक्ट को MessageVerifier के रहस्य के साथ हस्ताक्षर करके उत्पन्न किया जा सकता था।

verifier = ActiveSupport::MessageVerifier.new 's3Krit'
signed_message = verifier.generate 'a private message'
verifier.valid_message?(signed_message) # => true

tampered_message = signed_message.chop # editing the message invalidates the signature
verifier.valid_message?(tampered_message) # => false
सत्यापित (हस्ताक्षरित_समूह, उद्देश्य: शून्य, **) स्रोत दिखाएं
# File activesupport/lib/active_support/message_verifier.rb, line 150
def verified(signed_message, purpose: nil, **)
  if valid_message?(signed_message)
    begin
      data = signed_message.split("--".freeze)[0]
      message = Messages::Metadata.verify(decode(data), purpose)
      @serializer.load(message) if message
    rescue ArgumentError => argument_error
      return if argument_error.message.include?("invalid base64")
      raise
    end
  end
end

MessageVerifier के रहस्य का उपयोग करके हस्ताक्षरित संदेश को MessageVerifier है।

verifier = ActiveSupport::MessageVerifier.new 's3Krit'

signed_message = verifier.generate 'a private message'
verifier.verified(signed_message) # => 'a private message'

यदि संदेश एक ही रहस्य के साथ हस्ताक्षरित नहीं था, तो रिटर्न nil हो जाता है।

other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
other_verifier.verified(signed_message) # => nil

यदि संदेश Base64- एन्कोडेड नहीं है, तो nil लौटाता है।

invalid_message = "f--46a0120593880c733a53b6dad75b42ddc1c8996d"
verifier.verified(invalid_message) # => nil

हस्ताक्षरित संदेश को डिकोड करते समय उठाई गई कोई भी त्रुटि।

incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff"
verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format
सत्यापित करें (* args) स्रोत दिखाएं
# File activesupport/lib/active_support/message_verifier.rb, line 175
def verify(*args)
  verified(*args) || raise(InvalidSignature)
end

MessageVerifier के रहस्य का उपयोग करके हस्ताक्षरित संदेश को MessageVerifier है।

verifier = ActiveSupport::MessageVerifier.new 's3Krit'
signed_message = verifier.generate 'a private message'

verifier.verify(signed_message) # => 'a private message'

यदि संदेश एक ही रहस्य के साथ हस्ताक्षरित नहीं था या Base64- एन्कोडेड नहीं था, तो InvalidSignature हस्ताक्षर बढ़ाता है।

other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
other_verifier.verify(signed_message) # => ActiveSupport::MessageVerifier::InvalidSignature