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

raise if someone tries to modify the cookies when it was already streamed back to the client or converted to HTTP headers

This commit is contained in:
Santiago Pastorino 2011-04-06 12:05:58 -03:00
parent 90ecad0bc9
commit 0c5aded092
2 changed files with 63 additions and 0 deletions

View file

@ -115,10 +115,15 @@ module ActionDispatch
@delete_cookies = {} @delete_cookies = {}
@host = host @host = host
@secure = secure @secure = secure
@closed = false
super() super()
end end
attr_reader :closed
alias :closed? :closed
def close!; @closed = true end
# Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
def [](name) def [](name)
super(name.to_s) super(name.to_s)
@ -145,6 +150,7 @@ module ActionDispatch
# Sets the cookie named +name+. The second argument may be the very cookie # Sets the cookie named +name+. The second argument may be the very cookie
# value, or a hash of options as documented above. # value, or a hash of options as documented above.
def []=(key, options) def []=(key, options)
raise ClosedError, :cookies if closed?
if options.is_a?(Hash) if options.is_a?(Hash)
options.symbolize_keys! options.symbolize_keys!
value = options[:value] value = options[:value]
@ -225,6 +231,7 @@ module ActionDispatch
end end
def []=(key, options) def []=(key, options)
raise ClosedError, :cookies if closed?
if options.is_a?(Hash) if options.is_a?(Hash)
options.symbolize_keys! options.symbolize_keys!
else else
@ -263,6 +270,7 @@ module ActionDispatch
end end
def []=(key, options) def []=(key, options)
raise ClosedError, :cookies if closed?
if options.is_a?(Hash) if options.is_a?(Hash)
options.symbolize_keys! options.symbolize_keys!
options[:value] = @verifier.generate(options[:value]) options[:value] = @verifier.generate(options[:value])
@ -305,6 +313,7 @@ module ActionDispatch
end end
def call(env) def call(env)
cookie_jar = nil
status, headers, body = @app.call(env) status, headers, body = @app.call(env)
if cookie_jar = env['action_dispatch.cookies'] if cookie_jar = env['action_dispatch.cookies']
@ -315,6 +324,9 @@ module ActionDispatch
end end
[status, headers, body] [status, headers, body]
ensure
cookie_jar = ActionDispatch::Request.new(env).cookie_jar unless cookie_jar
cookie_jar.close!
end end
end end
end end

View file

@ -495,3 +495,54 @@ class CookiesTest < ActionController::TestCase
end end
end end
end end
class CookiesIntegrationTest < ActionDispatch::IntegrationTest
class TestController < ActionController::Base
def dont_set_cookies
head :ok
end
def set_cookies
cookies["that"] = "hello"
head :ok
end
end
def test_setting_cookies_raises_after_stream_back_to_client
with_test_route_set do
env = {}
get '/set_cookies', nil, env
assert_raise(ActionDispatch::ClosedError) {
request.cookie_jar['alert'] = 'alert'
cookies['alert'] = 'alert'
}
end
end
def test_setting_cookies_raises_after_stream_back_to_client_even_with_an_empty_flash
with_test_route_set do
env = {}
get '/dont_set_cookies', nil, {}
assert_raise(ActionDispatch::ClosedError) {
request.cookie_jar['alert'] = 'alert'
}
end
end
private
def with_test_route_set
with_routing do |set|
set.draw do
match ':action', :to => CookiesIntegrationTest::TestController
end
@app = self.class.build_app(set) do |middleware|
middleware.use ActionDispatch::Cookies
middleware.delete "ActionDispatch::ShowExceptions"
end
yield
end
end
end