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:
parent
393e19e508
commit
e158ee50e6
3 changed files with 50 additions and 2 deletions
|
@ -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'.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue