From b927d67decb9d4e5103b5991b7e26a4dab4eca92 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 4 Feb 2014 09:31:48 -0800 Subject: [PATCH] Renamed session_serializer option to cookies_serializer --- actionpack/lib/action_dispatch.rb | 2 - .../lib/action_dispatch/middleware/cookies.rb | 45 ++++++++++++------- .../middleware/session/json_serializer.rb | 13 ------ .../middleware/session/marshal_serializer.rb | 14 ------ actionpack/test/dispatch/cookies_test.rb | 12 ++--- guides/source/action_controller_overview.md | 43 +++++++++++------- railties/lib/rails/application.rb | 2 +- 7 files changed, 64 insertions(+), 67 deletions(-) delete mode 100644 actionpack/lib/action_dispatch/middleware/session/json_serializer.rb delete mode 100644 actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index a56d827b1a..3dd2e2a45c 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -84,8 +84,6 @@ module ActionDispatch autoload :CookieStore, 'action_dispatch/middleware/session/cookie_store' autoload :MemCacheStore, 'action_dispatch/middleware/session/mem_cache_store' autoload :CacheStore, 'action_dispatch/middleware/session/cache_store' - autoload :JsonSerializer, 'action_dispatch/middleware/session/json_serializer' - autoload :MarshalSerializer, 'action_dispatch/middleware/session/marshal_serializer' end mattr_accessor :test_app diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 531654895b..7e8a395d93 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -89,7 +89,7 @@ module ActionDispatch ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze SECRET_TOKEN = "action_dispatch.secret_token".freeze SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze - SESSION_SERIALIZER = "action_dispatch.session_serializer".freeze + COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze # Cookies can typically store 4096 bytes. MAX_COOKIE_SIZE = 4096 @@ -212,7 +212,7 @@ module ActionDispatch secret_token: env[SECRET_TOKEN], secret_key_base: env[SECRET_KEY_BASE], upgrade_legacy_signed_cookies: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present?, - session_serializer: env[SESSION_SERIALIZER] + serializer: env[COOKIES_SERIALIZER] } end @@ -374,14 +374,40 @@ module ActionDispatch end end + class JsonSerializer + def self.load(value) + JSON.parse(value, quirks_mode: true) + end + + def self.dump(value) + JSON.generate(value, quirks_mode: true) + end + end + + module SerializedCookieJars + protected + def serializer + serializer = @options[:serializer] || :marshal + case serializer + when :marshal + Marshal + when :json + JsonSerializer + else + serializer + end + end + end + class SignedCookieJar #:nodoc: include ChainedCookieJars + include SerializedCookieJars def initialize(parent_jar, key_generator, options = {}) @parent_jar = parent_jar @options = options secret = key_generator.generate_key(@options[:signed_cookie_salt]) - @verifier = ActiveSupport::MessageVerifier.new(secret) + @verifier = ActiveSupport::MessageVerifier.new(secret, serializer: serializer) end def [](name) @@ -426,6 +452,7 @@ module ActionDispatch class EncryptedCookieJar #:nodoc: include ChainedCookieJars + include SerializedCookieJars def initialize(parent_jar, key_generator, options = {}) if ActiveSupport::LegacyKeyGenerator === key_generator @@ -464,18 +491,6 @@ module ActionDispatch rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage nil end - - def serializer - serializer = @options[:session_serializer] || :marshal - case serializer - when :marshal - ActionDispatch::Session::MarshalSerializer - when :json - ActionDispatch::Session::JsonSerializer - else - serializer - end - end end # UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore diff --git a/actionpack/lib/action_dispatch/middleware/session/json_serializer.rb b/actionpack/lib/action_dispatch/middleware/session/json_serializer.rb deleted file mode 100644 index d341853f7a..0000000000 --- a/actionpack/lib/action_dispatch/middleware/session/json_serializer.rb +++ /dev/null @@ -1,13 +0,0 @@ -module ActionDispatch - module Session - class JsonSerializer - def self.load(value) - JSON.parse(value, quirks_mode: true) - end - - def self.dump(value) - JSON.generate(value, quirks_mode: true) - end - end - end -end diff --git a/actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb b/actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb deleted file mode 100644 index 26622f682d..0000000000 --- a/actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb +++ /dev/null @@ -1,14 +0,0 @@ -module ActionDispatch - module Session - class MarshalSerializer - def self.load(value) - Marshal.load(value) - end - - def self.dump(value) - Marshal.dump(value) - end - end - end -end - diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 6101acdc25..25a2fe199c 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -379,28 +379,28 @@ class CookiesTest < ActionController::TestCase assert_equal 'bar', cookies.encrypted[:foo] end - class CustomJsonSerializer + class CustomSerializer def self.load(value) - JSON.load(value) + " and loaded" + value.to_s + " and loaded" end def self.dump(value) - JSON.dump(value + " was dumped") + value.to_s + " was dumped" end end def test_encrypted_cookie_using_serializer_object - @request.env["action_dispatch.session_serializer"] = CustomJsonSerializer + @request.env["action_dispatch.cookies_serializer"] = CustomSerializer get :set_encrypted_cookie assert_equal 'bar was dumped and loaded', cookies.encrypted[:foo] end def test_encrypted_cookie_using_json_serializer - @request.env["action_dispatch.session_serializer"] = :json + @request.env["action_dispatch.cookies_serializer"] = :json get :set_encrypted_cookie cookies = @controller.send :cookies assert_not_equal 'bar', cookies[:foo] - assert_raises TypeError do + assert_raises ::JSON::ParserError do cookies.signed[:foo] end assert_equal 'bar', cookies.encrypted[:foo] diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index 9eaf03dd82..b142279991 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -381,22 +381,6 @@ You can also pass a `:domain` key and specify the domain name for the cookie: YourApp::Application.config.session_store :cookie_store, key: '_your_app_session', domain: ".example.com" ``` -You can pass `:serializer` key to specify serializer for serializing session: - -```ruby -YourApp::Application.config.session_store :cookie_store, key: '_your_app_session', serializer: :json -``` - -The default serializer for new application is `:json`. For compatibility with -old applications `:marshal` is used when `serializer` option is not specified. - -It is also possible to pass a custom serializer class with `load` and `dump` -public methods defined: - -```ruby -YourApp::Application.config.session_store :cookie_store, key: '_your_app_session', serializer: MyCustomSerializer -``` - Rails sets up (for the CookieStore) a secret key used for signing the session data. This can be changed in `config/initializers/secret_token.rb` ```ruby @@ -588,6 +572,33 @@ end Note that while for session values you set the key to `nil`, to delete a cookie value you should use `cookies.delete(:key)`. +Rails also provides a signed cookie jar and an encrypted cookie jar for storing +sensitive data. The signed cookie jar appends a cryptographic signature on the +cookie values to protect their integrity. The encrypted cookie jar encrypts the +values in addition to signing them, so that they cannot be read by the end user. +Refer to the [API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html) +for more details. + +These special cookie jars use a serializer to serialize the assigned values into +strings and deserializes them into Ruby objects on read. + +You can specify what serializer to use: + +```ruby +YourApp::Application.config.cookies_serializer :json +``` + +The possible options are `:marshal` or `:json`. The default serializer for new +applications is `:json`. For compatibility with old applications with existing +cookies, `:marshal` is used when `serializer` option is not specified. + +It is also possible to pass a custom serializer class or object that responds +to `load` and `dump`: + +```ruby +YourApp::Application.config.cookies_serializer MyCustomSerializer +``` + Rendering XML and JSON data --------------------------- diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 36432e56ba..d018247c5a 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -206,7 +206,7 @@ module Rails "action_dispatch.signed_cookie_salt" => config.action_dispatch.signed_cookie_salt, "action_dispatch.encrypted_cookie_salt" => config.action_dispatch.encrypted_cookie_salt, "action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt, - "action_dispatch.session_serializer" => config.session_options[:serializer] + "action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer }) end end