1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Use AS::JSON for (de)serializing cookies

Use the Active Support JSON encoder for cookie jars using the `:json` or
`:hybrid` serializer. This allows you to serialize custom Ruby objects into
cookies by defining the `#as_json` hook on such objects.

Fixes #16520.
This commit is contained in:
Godfrey Chan 2014-08-17 12:40:24 -07:00
parent 393e19e508
commit e158ee50e6
3 changed files with 50 additions and 2 deletions

View file

@ -1,3 +1,11 @@
* Use the Active Support JSON encoder for cookie jars using the `:json` or
`:hybrid` serializer. This allows you to serialize custom Ruby objects into
cookies by defining the `#as_json` hook on such objects.
Fixes #16520.
*Godfrey Chan*
* Add `config.action_dispatch.cookies_digest` option for setting custom
digest. The default remains the same - 'SHA1'.

View file

@ -3,6 +3,7 @@ require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/object/blank'
require 'active_support/key_generator'
require 'active_support/message_verifier'
require 'active_support/json'
module ActionDispatch
class Request < Rack::Request
@ -391,11 +392,11 @@ module ActionDispatch
class JsonSerializer
def self.load(value)
JSON.parse(value, quirks_mode: true)
ActiveSupport::JSON.decode(value)
end
def self.dump(value)
JSON.generate(value, quirks_mode: true)
ActiveSupport::JSON.encode(value)
end
end

View file

@ -21,6 +21,16 @@ class CookiesTest < ActionController::TestCase
end
end
class JSONWrapper
def initialize(obj)
@obj = obj
end
def as_json(options = nil)
"wrapped: #{@obj.as_json(options)}"
end
end
class TestController < ActionController::Base
def authenticate
cookies["user_name"] = "david"
@ -85,6 +95,11 @@ class CookiesTest < ActionController::TestCase
head :ok
end
def set_wrapped_signed_cookie
cookies.signed[:user_id] = JSONWrapper.new(45)
head :ok
end
def get_signed_cookie
cookies.signed[:user_id]
head :ok
@ -95,6 +110,11 @@ class CookiesTest < ActionController::TestCase
head :ok
end
def set_wrapped_encrypted_cookie
cookies.encrypted[:foo] = JSONWrapper.new('bar')
head :ok
end
def get_encrypted_cookie
cookies.encrypted[:foo]
head :ok
@ -421,6 +441,14 @@ class CookiesTest < ActionController::TestCase
assert_equal 45, cookies.signed[:user_id]
end
def test_wrapped_signed_cookie_using_json_serializer
@request.env["action_dispatch.cookies_serializer"] = :json
get :set_wrapped_signed_cookie
cookies = @controller.send :cookies
assert_not_equal 'wrapped: 45', cookies[:user_id]
assert_equal 'wrapped: 45', cookies.signed[:user_id]
end
def test_signed_cookie_using_custom_serializer
@request.env["action_dispatch.cookies_serializer"] = CustomSerializer
get :set_signed_cookie
@ -503,6 +531,17 @@ class CookiesTest < ActionController::TestCase
assert_equal 'bar', cookies.encrypted[:foo]
end
def test_wrapped_encrypted_cookie_using_json_serializer
@request.env["action_dispatch.cookies_serializer"] = :json
get :set_wrapped_encrypted_cookie
cookies = @controller.send :cookies
assert_not_equal 'wrapped: bar', cookies[:foo]
assert_raises ::JSON::ParserError do
cookies.signed[:foo]
end
assert_equal 'wrapped: bar', cookies.encrypted[:foo]
end
def test_encrypted_cookie_using_custom_serializer
@request.env["action_dispatch.cookies_serializer"] = CustomSerializer
get :set_encrypted_cookie