From ed708307137c811d14e5fd2cb4ea550add381a82 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Mon, 15 Dec 2008 16:33:31 -0600 Subject: Switch to Rack based session stores. --- .../test/controller/session/cookie_store_test.rb | 348 ++++++--------------- 1 file changed, 98 insertions(+), 250 deletions(-) (limited to 'actionpack/test/controller/session/cookie_store_test.rb') diff --git a/actionpack/test/controller/session/cookie_store_test.rb b/actionpack/test/controller/session/cookie_store_test.rb index b5f14acc1f..8098059d46 100644 --- a/actionpack/test/controller/session/cookie_store_test.rb +++ b/actionpack/test/controller/session/cookie_store_test.rb @@ -1,298 +1,146 @@ require 'abstract_unit' require 'stringio' +class CookieStoreTest < ActionController::IntegrationTest + SessionKey = '_myapp_session' + SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' -class CGI::Session::CookieStore - def ensure_secret_secure_with_test_hax(secret) - if secret == CookieStoreTest.default_session_options['secret'] - return true - else - ensure_secret_secure_without_test_hax(secret) - end - end - alias_method_chain :ensure_secret_secure, :test_hax -end + DispatcherApp = ActionController::Dispatcher.new + CookieStoreApp = ActionController::Session::CookieStore.new(DispatcherApp, + :key => SessionKey, :secret => SessionSecret) + SignedBar = "BAh7BjoIZm9vIghiYXI%3D--" + + "fef868465920f415f2c0652d6910d3af288a0367" -# Expose for tests. -class CGI - attr_reader :output_cookies, :output_hidden - - class Session - attr_reader :dbman + class TestController < ActionController::Base + def no_session_access + head :ok + end - class CookieStore - attr_reader :data, :original, :cookie_options + def set_session_value + session[:foo] = "bar" + head :ok end - end -end -class CookieStoreTest < Test::Unit::TestCase - def self.default_session_options - { 'database_manager' => CGI::Session::CookieStore, - 'session_key' => '_myapp_session', - 'secret' => 'Keep it secret; keep it safe.', - 'no_cookies' => true, - 'no_hidden' => true, - 'session_http_only' => true - } - end + def get_session_value + render :text => "foo: #{session[:foo].inspect}" + end - def self.cookies - { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}], - :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }], - :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], - :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }] - } + def raise_data_overflow + session[:foo] = 'bye!' * 1024 + head :ok + end + def rescue_action(e) raise end end def setup - ENV.delete('HTTP_COOKIE') + @integration_session = open_session(CookieStoreApp) end def test_raises_argument_error_if_missing_session_key - [nil, ''].each do |blank| - assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank } - end + assert_raise(ArgumentError, nil.inspect) { + ActionController::Session::CookieStore.new(nil, + :key => nil, :secret => SessionSecret) + } + + assert_raise(ArgumentError, ''.inspect) { + ActionController::Session::CookieStore.new(nil, + :key => '', :secret => SessionSecret) + } end def test_raises_argument_error_if_missing_secret - [nil, ''].each do |blank| - assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } - end - end + assert_raise(ArgumentError, nil.inspect) { + ActionController::Session::CookieStore.new(nil, + :key => SessionKey, :secret => nil) + } - def test_raises_argument_error_if_secret_is_probably_insecure - ["password", "secret", "12345678901234567890123456789"].each do |blank| - assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank } - end + assert_raise(ArgumentError, ''.inspect) { + ActionController::Session::CookieStore.new(nil, + :key => SessionKey, :secret => '') + } end - def test_reconfigures_session_to_omit_id_cookie_and_hidden_field - new_session do |session| - assert_equal true, @options['no_hidden'] - assert_equal true, @options['no_cookies'] - end - end + def test_raises_argument_error_if_secret_is_probably_insecure + assert_raise(ArgumentError, "password".inspect) { + ActionController::Session::CookieStore.new(nil, + :key => SessionKey, :secret => "password") + } - def test_restore_unmarshals_missing_cookie_as_empty_hash - new_session do |session| - assert_nil session.dbman.data - assert_nil session['test'] - assert_equal Hash.new, session.dbman.data - end - end + assert_raise(ArgumentError, "secret".inspect) { + ActionController::Session::CookieStore.new(nil, + :key => SessionKey, :secret => "secret") + } - def test_restore_unmarshals_good_cookies - cookies(:empty, :a_one, :typical).each do |value, expected| - set_cookie! value - new_session do |session| - assert_nil session['lazy loads the data hash'] - assert_equal expected, session.dbman.data - end - end + assert_raise(ArgumentError, "12345678901234567890123456789".inspect) { + ActionController::Session::CookieStore.new(nil, + :key => SessionKey, :secret => "12345678901234567890123456789") + } end - def test_restore_deletes_tampered_cookies - set_cookie! 'a--b' - new_session do |session| - assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] } - assert_cookie_deleted session - end + def test_setting_session_value + with_test_route_set do + get '/set_session_value' + assert_response :success + assert_equal ["_myapp_session=#{SignedBar}; path=/"], + headers['Set-Cookie'] + end end - def test_close_doesnt_write_cookie_if_data_is_blank - new_session do |session| - assert_no_cookies session - session.close - assert_no_cookies session - end + def test_getting_session_value + with_test_route_set do + cookies[SessionKey] = SignedBar + get '/get_session_value' + assert_response :success + assert_equal 'foo: "bar"', response.body + end end - def test_close_doesnt_write_cookie_if_data_is_unchanged - set_cookie! cookie_value(:typical) - new_session do |session| - assert_no_cookies session - session['user_id'] = session['user_id'] - session.close - assert_no_cookies session + def test_disregards_tampered_sessions + with_test_route_set do + cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--123456780" + get '/get_session_value' + assert_response :success + assert_equal 'foo: nil', response.body end end def test_close_raises_when_data_overflows - set_cookie! cookie_value(:empty) - new_session do |session| - session['overflow'] = 'bye!' * 1024 - assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close } - assert_no_cookies session - end - end - - def test_close_marshals_and_writes_cookie - set_cookie! cookie_value(:typical) - new_session do |session| - assert_no_cookies session - session['flash'] = {} - assert_no_cookies session - session.close - assert_equal 1, session.cgi.output_cookies.size - cookie = session.cgi.output_cookies.first - assert_cookie cookie, cookie_value(:flashed) - assert_http_only_cookie cookie - assert_secure_cookie cookie, false - end - end - - def test_writes_non_secure_cookie_by_default - set_cookie! cookie_value(:typical) - new_session do |session| - session['flash'] = {} - session.close - cookie = session.cgi.output_cookies.first - assert_secure_cookie cookie,false - end - end - - def test_writes_secure_cookie - set_cookie! cookie_value(:typical) - new_session('session_secure'=>true) do |session| - session['flash'] = {} - session.close - cookie = session.cgi.output_cookies.first - assert_secure_cookie cookie + with_test_route_set do + assert_raise(ActionController::Session::CookieStore::CookieOverflow) { + get '/raise_data_overflow' + } end end - def test_http_only_cookie_by_default - set_cookie! cookie_value(:typical) - new_session do |session| - session['flash'] = {} - session.close - cookie = session.cgi.output_cookies.first - assert_http_only_cookie cookie + def test_doesnt_write_session_cookie_if_session_is_not_accessed + with_test_route_set do + get '/no_session_access' + assert_response :success + assert_equal [], headers['Set-Cookie'] end end - def test_overides_http_only_cookie - set_cookie! cookie_value(:typical) - new_session('session_http_only'=>false) do |session| - session['flash'] = {} - session.close - cookie = session.cgi.output_cookies.first - assert_http_only_cookie cookie, false - end - end - - def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil - set_cookie! cookie_value(:typical) - new_session do |session| - assert_no_cookies session - session.delete - assert_cookie_deleted session - - # @data is set to nil so #close doesn't send another cookie. - session.close - assert_cookie_deleted session - end - end - - def test_new_session_doesnt_reuse_deleted_cookie_data - set_cookie! cookie_value(:typical) - - new_session do |session| - assert_not_nil session['user_id'] - session.delete - - # Start a new session using the same CGI instance. - post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options) - assert_nil post_delete_session['user_id'] + def test_doesnt_write_session_cookie_if_session_is_unchanged + with_test_route_set do + cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--" + + "fef868465920f415f2c0652d6910d3af288a0367" + get '/no_session_access' + assert_response :success + assert_equal [], headers['Set-Cookie'] end end private - def assert_no_cookies(session) - assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect - end - - def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set') - assert_equal 1, session.cgi.output_cookies.size - cookie = session.cgi.output_cookies.first - assert_cookie cookie, nil, 1.year.ago.to_date, "#{message}: #{cookie.name} => #{cookie.value}" - end - - def assert_cookie(cookie, value = nil, expires = nil, message = nil) - assert_equal '_myapp_session', cookie.name, message - assert_equal [value].compact, cookie.value, message - assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message - end - - def assert_secure_cookie(cookie,value=true) - assert cookie.secure==value - end - - def assert_http_only_cookie(cookie,value=true) - assert cookie.http_only==value - end - - def cookies(*which) - self.class.cookies.values_at(*which) - end - - def cookie_value(which) - self.class.cookies[which].first - end - - def set_cookie!(value) - ENV['HTTP_COOKIE'] = "_myapp_session=#{value}" - end - - def new_session(options = {}) - with_cgi do |cgi| - assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" - assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" - - @options = self.class.default_session_options.merge(options) - session = CGI::Session.new(cgi, @options) - ObjectSpace.undefine_finalizer(session) - - assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}" - assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}" - - yield session if block_given? - session + def with_test_route_set + with_routing do |set| + set.draw do |map| + map.with_options :controller => "cookie_store_test/test" do |c| + c.connect "/:action" + end + end + yield end end - - def with_cgi - ENV['REQUEST_METHOD'] = 'GET' - ENV['HTTP_HOST'] = 'example.com' - ENV['QUERY_STRING'] = '' - - cgi = CGI.new('query', StringIO.new('')) - yield cgi if block_given? - cgi - end -end - - -class CookieStoreWithBlockAsSecretTest < CookieStoreTest - def self.default_session_options - CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' } - end -end - - -class CookieStoreWithMD5DigestTest < CookieStoreTest - def self.default_session_options - CookieStoreTest.default_session_options.merge 'digest' => 'MD5' - end - - def self.cookies - { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}], - :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }], - :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], - :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }], - :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] } - end end -- cgit v1.2.3