aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/middleware/cookies.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/cookies.rb')
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb128
1 files changed, 48 insertions, 80 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index f958a88e4b..b653e4eacd 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -4,9 +4,9 @@ require 'active_support/message_verifier'
require 'active_support/json'
module ActionDispatch
- class Request < Rack::Request
+ class Request
def cookie_jar
- get_header('action_dispatch.cookies'.freeze) do
+ fetch_header('action_dispatch.cookies'.freeze) do
self.cookie_jar = Cookies::CookieJar.build(self, cookies)
end
end
@@ -221,19 +221,11 @@ module ActionDispatch
end
end
- protected
-
- def request; @parent_jar.request; end
-
private
def upgrade_legacy_signed_cookies?
request.secret_token.present? && request.secret_key_base.present?
end
-
- def key_generator
- request.key_generator
- end
end
# Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream
@@ -253,6 +245,11 @@ module ActionDispatch
rescue ActiveSupport::MessageVerifier::InvalidSignature
nil
end
+
+ private
+ def parse(name, signed_message)
+ super || verify_and_upgrade_legacy_signed_message(name, signed_message)
+ end
end
class CookieJar #:nodoc:
@@ -412,7 +409,7 @@ module ActionDispatch
end
end
- class PermanentCookieJar #:nodoc:
+ class AbstractCookieJar # :nodoc:
include ChainedCookieJars
def initialize(parent_jar)
@@ -420,19 +417,35 @@ module ActionDispatch
end
def [](name)
- @parent_jar[name.to_s]
+ if data = @parent_jar[name.to_s]
+ parse name, data
+ end
end
def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
else
- options = { :value => options }
+ options = { value: options }
end
- options[:expires] = 20.years.from_now
+ commit(options)
@parent_jar[name] = options
end
+
+ protected
+ def request; @parent_jar.request; end
+
+ private
+ def parse(name, data); data; end
+ def commit(options); end
+ end
+
+ class PermanentCookieJar < AbstractCookieJar # :nodoc:
+ private
+ def commit(options)
+ options[:expires] = 20.years.from_now
+ end
end
class JsonSerializer # :nodoc:
@@ -484,45 +497,30 @@ module ActionDispatch
def digest
request.cookies_digest || 'SHA1'
end
+
+ def key_generator
+ request.key_generator
+ end
end
- class SignedCookieJar #:nodoc:
- include ChainedCookieJars
+ class SignedCookieJar < AbstractCookieJar # :nodoc:
include SerializedCookieJars
def initialize(parent_jar)
- @parent_jar = parent_jar
+ super
secret = key_generator.generate_key(request.signed_cookie_salt)
@verifier = ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
- # Returns the value of the cookie by +name+ if it is untampered,
- # returns +nil+ otherwise or if no such cookie exists.
- def [](name)
- if signed_message = @parent_jar[name]
- deserialize name, verify(signed_message)
+ private
+ def parse(name, signed_message)
+ deserialize name, @verifier.verified(signed_message)
end
- end
- # Signs and sets the cookie named +name+. The second argument may be the cookie's
- # value or a hash of options as documented above.
- def []=(name, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
+ def commit(options)
options[:value] = @verifier.generate(serialize(options[:value]))
- else
- options = { :value => @verifier.generate(serialize(options)) }
- end
- raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
- @parent_jar[name] = options
- end
-
- private
- def verify(signed_message)
- @verifier.verify(signed_message)
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
end
end
@@ -532,20 +530,13 @@ module ActionDispatch
# re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
include VerifyAndUpgradeLegacySignedMessage
-
- def [](name)
- if signed_message = @parent_jar[name]
- deserialize(name, verify(signed_message)) || verify_and_upgrade_legacy_signed_message(name, signed_message)
- end
- end
end
- class EncryptedCookieJar #:nodoc:
- include ChainedCookieJars
+ class EncryptedCookieJar < AbstractCookieJar # :nodoc:
include SerializedCookieJars
def initialize(parent_jar)
- @parent_jar = parent_jar
+ super
if ActiveSupport::LegacyKeyGenerator === key_generator
raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " +
@@ -557,35 +548,18 @@ module ActionDispatch
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
- # Returns the value of the cookie by +name+ if it is untampered,
- # returns +nil+ otherwise or if no such cookie exists.
- def [](name)
- if encrypted_message = @parent_jar[name]
- deserialize name, decrypt_and_verify(encrypted_message)
- end
- end
-
- # Encrypts and sets the cookie named +name+. The second argument may be the cookie's
- # value or a hash of options as documented above.
- def []=(name, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
- else
- options = { :value => options }
- end
-
- options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]))
-
- raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
- @parent_jar[name] = options
- end
-
private
- def decrypt_and_verify(encrypted_message)
- @encryptor.decrypt_and_verify(encrypted_message)
+ def parse(name, encrypted_message)
+ deserialize name, @encryptor.decrypt_and_verify(encrypted_message)
rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
nil
end
+
+ def commit(options)
+ options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]))
+
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
+ end
end
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
@@ -594,12 +568,6 @@ module ActionDispatch
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
include VerifyAndUpgradeLegacySignedMessage
-
- def [](name)
- if encrypted_or_signed_message = @parent_jar[name]
- deserialize(name, decrypt_and_verify(encrypted_or_signed_message)) || verify_and_upgrade_legacy_signed_message(name, encrypted_or_signed_message)
- end
- end
end
def initialize(app)