aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md14
-rw-r--r--actionpack/lib/action_dispatch.rb10
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb16
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/json_serializer.rb13
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb14
-rw-r--r--actionpack/test/dispatch/cookies_test.rb33
6 files changed, 94 insertions, 6 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index fc05ae3cec..60b0195510 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -49,6 +49,20 @@
*Alessandro Diaferia*
+* Add `:serializer` option for `config.session_store :cookie_store`. This
+ changes default serializer when using `:cookie_store` to
+ `ActionDispatch::Session::MarshalSerializer` which is wrapper on Marshal.
+
+ It is also possible to pass:
+
+ * `:json_serializer` which is secure wrapper on JSON using `JSON.parse` and
+ `JSON.generate` methods with quirks mode;
+ * any other Symbol or String like `:my_custom_serializer` which will be
+ camelized and constantized in `ActionDispatch::Session` namespace;
+ * serializer object with `load` and `dump` methods defined.
+
+ *Ɓukasz Sarnacki*
+
* Allow an absolute controller path inside a module scope. Fixes #12777.
Example:
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 920e651b08..36dcca2905 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -82,10 +82,12 @@ module ActionDispatch
end
module Session
- autoload :AbstractStore, 'action_dispatch/middleware/session/abstract_store'
- 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 :AbstractStore, 'action_dispatch/middleware/session/abstract_store'
+ 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 fe110d7938..f9f034952e 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -89,6 +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 can typically store 4096 bytes.
MAX_COOKIE_SIZE = 4096
@@ -210,7 +211,8 @@ module ActionDispatch
encrypted_signed_cookie_salt: env[ENCRYPTED_SIGNED_COOKIE_SALT] || '',
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?
+ upgrade_legacy_signed_cookies: env[SECRET_TOKEN].present? && env[SECRET_KEY_BASE].present?,
+ session_serializer: env[SESSION_SERIALIZER]
}
end
@@ -435,7 +437,7 @@ module ActionDispatch
@options = options
secret = key_generator.generate_key(@options[:encrypted_cookie_salt])
sign_secret = key_generator.generate_key(@options[:encrypted_signed_cookie_salt])
- @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
+ @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: serializer)
end
def [](name)
@@ -462,6 +464,16 @@ module ActionDispatch
rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
nil
end
+
+ def serializer
+ serializer = @options[:session_serializer] || :marshal_serializer
+ case serializer
+ when Symbol, String
+ ActionDispatch::Session.const_get(serializer.to_s.camelize)
+ 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
new file mode 100644
index 0000000000..d341853f7a
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/session/json_serializer.rb
@@ -0,0 +1,13 @@
+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
new file mode 100644
index 0000000000..26622f682d
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/session/marshal_serializer.rb
@@ -0,0 +1,14 @@
+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 91ac13e7c6..b19ce905f5 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -379,6 +379,39 @@ class CookiesTest < ActionController::TestCase
assert_equal 'bar', cookies.encrypted[:foo]
end
+ class ActionDispatch::Session::CustomJsonSerializer
+ def self.load(value)
+ JSON.load(value) + " and loaded"
+ end
+
+ def self.dump(value)
+ JSON.dump(value + " was dumped")
+ end
+ end
+
+ def test_encrypted_cookie_using_custom_json_serializer
+ @request.env["action_dispatch.session_serializer"] = :custom_json_serializer
+ get :set_encrypted_cookie
+ assert_equal 'bar was dumped and loaded', cookies.encrypted[:foo]
+ end
+
+ def test_encrypted_cookie_using_serializer_object
+ @request.env["action_dispatch.session_serializer"] = ActionDispatch::Session::CustomJsonSerializer
+ 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_serializer
+ get :set_encrypted_cookie
+ cookies = @controller.send :cookies
+ assert_not_equal 'bar', cookies[:foo]
+ assert_raises TypeError do
+ cookies.signed[:foo]
+ end
+ assert_equal 'bar', cookies.encrypted[:foo]
+ end
+
def test_accessing_nonexistant_encrypted_cookie_should_not_raise_invalid_message
get :set_encrypted_cookie
assert_nil @controller.send(:cookies).encrypted[:non_existant_attribute]