Fix reset_session with lazy cookie stores [#1601 state:resolved]

Signed-off-by: Joshua Peek <josh@joshpeek.com>
This commit is contained in:
Matt Bauer 2008-12-20 14:37:51 -06:00 committed by Joshua Peek
parent 462c75b60c
commit 7b249b67e9
4 changed files with 64 additions and 13 deletions

View File

@ -53,6 +53,10 @@ module ActionController
end
private
def loaded?
@loaded
end
def load!
@id, session = @by.send(:load_session, @env)
replace(session)
@ -91,19 +95,23 @@ module ActionController
def call(env)
session = SessionHash.new(self, env)
original_session = session.dup
env[ENV_SESSION_KEY] = session
env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
response = @app.call(env)
session = env[ENV_SESSION_KEY]
unless session == original_session
session_data = env[ENV_SESSION_KEY]
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.send(:loaded?)
options = env[ENV_SESSION_OPTIONS_KEY]
sid = session.id
unless set_session(env, sid, session.to_hash)
if session_data.is_a?(AbstractStore::SessionHash)
sid = session_data.id
else
sid = generate_sid
end
unless set_session(env, sid, session_data.to_hash)
return response
end

View File

@ -89,16 +89,14 @@ module ActionController
end
def call(env)
session_data = AbstractStore::SessionHash.new(self, env)
original_value = session_data.dup
env[ENV_SESSION_KEY] = session_data
env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env)
env[ENV_SESSION_OPTIONS_KEY] = @default_options
status, headers, body = @app.call(env)
unless env[ENV_SESSION_KEY] == original_value
session_data = marshal(env[ENV_SESSION_KEY].to_hash)
session_data = env[ENV_SESSION_KEY]
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.send(:loaded?)
session_data = marshal(session_data.to_hash)
raise CookieOverflow if session_data.size > MAX
@ -153,7 +151,7 @@ module ActionController
# Marshal a session hash into safe cookie data. Include an integrity hash.
def marshal(session)
@verifier.generate( persistent_session_id!(session))
@verifier.generate(persistent_session_id!(session))
end
# Unmarshal cookie data to a hash and verify its integrity.

View File

@ -32,6 +32,11 @@ class CookieStoreTest < ActionController::IntegrationTest
render :text => "foo: #{session[:foo].inspect}"
end
def call_reset_session
reset_session
head :ok
end
def raise_data_overflow
session[:foo] = 'bye!' * 1024
head :ok
@ -89,7 +94,7 @@ class CookieStoreTest < ActionController::IntegrationTest
with_test_route_set do
get '/set_session_value'
assert_response :success
session_payload = Verifier.generate( Marshal.load(response.body) )
session_payload = Verifier.generate(Marshal.load(response.body))
assert_equal ["_myapp_session=#{session_payload}; path=/"],
headers['Set-Cookie']
end
@ -139,6 +144,25 @@ class CookieStoreTest < ActionController::IntegrationTest
end
end
def test_setting_session_value_after_session_reset
with_test_route_set do
get '/set_session_value'
assert_response :success
session_payload = Verifier.generate(Marshal.load(response.body))
assert_equal ["_myapp_session=#{session_payload}; path=/"],
headers['Set-Cookie']
get '/call_reset_session'
assert_response :success
assert_not_equal [], headers['Set-Cookie']
assert_not_equal session_payload, cookies[SessionKey]
get '/get_session_value'
assert_response :success
assert_equal 'foo: nil', response.body
end
end
def test_persistent_session_id
with_test_route_set do
cookies[SessionKey] = SignedBar

View File

@ -16,6 +16,11 @@ class MemCacheStoreTest < ActionController::IntegrationTest
render :text => "foo: #{session[:foo].inspect}"
end
def call_reset_session
reset_session
head :ok
end
def rescue_action(e) raise end
end
@ -63,6 +68,22 @@ class MemCacheStoreTest < ActionController::IntegrationTest
assert_equal nil, cookies['_session_id']
end
end
def test_setting_session_value_after_session_reset
with_test_route_set do
get '/set_session_value'
assert_response :success
assert cookies['_session_id']
get '/call_reset_session'
assert_response :success
assert_not_equal [], headers['Set-Cookie']
get '/get_session_value'
assert_response :success
assert_equal 'foo: nil', response.body
end
end
rescue LoadError, RuntimeError
$stderr.puts "Skipping MemCacheStoreTest tests. Start memcached and try again."
end