diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/cookies.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/cookies.rb | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 41c4523ecb..cf4f654ed6 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -8,7 +8,16 @@ require 'active_support/json' module ActionDispatch class Request < Rack::Request def cookie_jar - env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self, cookies) + env['action_dispatch.cookies'.freeze] ||= Cookies::CookieJar.build(self, cookies) + end + + # :stopdoc: + def have_cookie_jar? + env.key? 'action_dispatch.cookies'.freeze + end + + def cookie_jar=(jar) + env['action_dispatch.cookies'.freeze] = jar end def key_generator @@ -42,6 +51,7 @@ module ActionDispatch def cookies_digest env[Cookies::COOKIES_DIGEST] end + # :startdoc: end # \Cookies are read and written through ActionController#cookies. @@ -150,7 +160,7 @@ module ActionDispatch # cookies.permanent.signed[:remember_me] = current_user.id # # => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT def permanent - @permanent ||= PermanentCookieJar.new(self, @request) + @permanent ||= PermanentCookieJar.new(self) end # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from @@ -171,9 +181,9 @@ module ActionDispatch def signed @signed ||= if upgrade_legacy_signed_cookies? - UpgradeLegacySignedCookieJar.new(self, @request) + UpgradeLegacySignedCookieJar.new(self) else - SignedCookieJar.new(self, @request) + SignedCookieJar.new(self) end end @@ -194,9 +204,9 @@ module ActionDispatch def encrypted @encrypted ||= if upgrade_legacy_signed_cookies? - UpgradeLegacyEncryptedCookieJar.new(self, @request) + UpgradeLegacyEncryptedCookieJar.new(self) else - EncryptedCookieJar.new(self, @request) + EncryptedCookieJar.new(self) end end @@ -204,21 +214,25 @@ module ActionDispatch # Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores. def signed_or_encrypted @signed_or_encrypted ||= - if @request.secret_key_base.present? + if request.secret_key_base.present? encrypted else signed end end + protected + + def request; @parent_jar.request; end + private def upgrade_legacy_signed_cookies? - @request.secret_token.present? && @request.secret_key_base.present? + request.secret_token.present? && request.secret_key_base.present? end def key_generator - @request.key_generator + request.key_generator end end @@ -229,7 +243,7 @@ module ActionDispatch module VerifyAndUpgradeLegacySignedMessage # :nodoc: def initialize(*args) super - @legacy_verifier = ActiveSupport::MessageVerifier.new(@request.secret_token, serializer: ActiveSupport::MessageEncryptor::NullSerializer) + @legacy_verifier = ActiveSupport::MessageVerifier.new(request.secret_token, serializer: ActiveSupport::MessageEncryptor::NullSerializer) end def verify_and_upgrade_legacy_signed_message(name, signed_message) @@ -264,6 +278,8 @@ module ActionDispatch end end + attr_reader :request + def initialize(request) @set_cookies = {} @delete_cookies = {} @@ -316,12 +332,12 @@ module ActionDispatch # if host is not ip and matches domain regexp # (ip confirms to domain regexp so we explicitly check for ip) - options[:domain] = if (@request.host !~ /^[\d.]+$/) && (@request.host =~ domain_regexp) + options[:domain] = if (request.host !~ /^[\d.]+$/) && (request.host =~ domain_regexp) ".#{$&}" end elsif options[:domain].is_a? Array # if host matches one of the supplied domains without a dot in front of it - options[:domain] = options[:domain].find {|domain| @request.host.include? domain.sub(/^\./, '') } + options[:domain] = options[:domain].find {|domain| request.host.include? domain.sub(/^\./, '') } end end @@ -380,26 +396,20 @@ module ActionDispatch @delete_cookies.each { |k, v| ::Rack::Utils.delete_cookie_header!(headers, k, v) } end - def recycle! #:nodoc: - @set_cookies = {} - @delete_cookies = {} - end - mattr_accessor :always_write_cookie self.always_write_cookie = false private def write_cookie?(cookie) - @request.ssl? || !cookie[:secure] || always_write_cookie + request.ssl? || !cookie[:secure] || always_write_cookie end end class PermanentCookieJar #:nodoc: include ChainedCookieJars - def initialize(parent_jar, request) + def initialize(parent_jar) @parent_jar = parent_jar - @request = request end def [](name) @@ -433,7 +443,7 @@ module ActionDispatch protected def needs_migration?(value) - @request.cookies_serializer == :hybrid && value.start_with?(MARSHAL_SIGNATURE) + request.cookies_serializer == :hybrid && value.start_with?(MARSHAL_SIGNATURE) end def serialize(value) @@ -453,7 +463,7 @@ module ActionDispatch end def serializer - serializer = @request.cookies_serializer || :marshal + serializer = request.cookies_serializer || :marshal case serializer when :marshal Marshal @@ -465,7 +475,7 @@ module ActionDispatch end def digest - @request.cookies_digest || 'SHA1' + request.cookies_digest || 'SHA1' end end @@ -473,9 +483,8 @@ module ActionDispatch include ChainedCookieJars include SerializedCookieJars - def initialize(parent_jar, request) + def initialize(parent_jar) @parent_jar = parent_jar - @request = request secret = key_generator.generate_key(request.signed_cookie_salt) @verifier = ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) end @@ -528,15 +537,14 @@ module ActionDispatch include ChainedCookieJars include SerializedCookieJars - def initialize(parent_jar, request) - @request = request + def initialize(parent_jar) + @parent_jar = parent_jar if ActiveSupport::LegacyKeyGenerator === key_generator raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " + "Read the upgrade documentation to learn more about this new config option." end - @parent_jar = parent_jar secret = key_generator.generate_key(request.encrypted_cookie_salt || '') sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || '') @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) @@ -592,9 +600,12 @@ module ActionDispatch end def call(env) + request = ActionDispatch::Request.new env + status, headers, body = @app.call(env) - if cookie_jar = env['action_dispatch.cookies'] + if request.have_cookie_jar? + cookie_jar = request.cookie_jar unless cookie_jar.committed? cookie_jar.write(headers) if headers[HTTP_HEADER].respond_to?(:join) |