From e311622e7b20b3fdeab6a93418c8a45c6e7137b6 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Thu, 4 Mar 2010 15:06:25 -0800 Subject: [PATCH] Deprecated ActionController::Base.session_options= and ActionController::Base.session_store= in favor of a config.session_store method (which takes params) and a config.cookie_secret variable, which is used in various secret scenarios. The old AC::Base options will continue to work with deprecation warnings. --- .../lib/action_controller/deprecated/base.rb | 17 ++++++++-- .../metal/http_authentication.rb | 4 +-- .../metal/session_management.rb | 30 ---------------- actionpack/lib/action_controller/railtie.rb | 4 +-- .../middleware/session/cookie_store.rb | 12 +++---- actionpack/lib/action_dispatch/railtie.rb | 2 -- actionpack/test/abstract_unit.rb | 3 +- .../http_digest_authentication_test.rb | 5 +-- .../cookie_verification_secret.rb.tt | 2 +- .../config/initializers/session_store.rb.tt | 9 ++--- railties/lib/rails/engine/configuration.rb | 1 + railties/lib/rails/railtie/configuration.rb | 34 +++++++++++++++++-- .../test/application/configuration_test.rb | 6 ++-- .../initializers/frameworks_test.rb | 4 +-- .../middleware_stack_defaults_test.rb | 3 +- .../test/application/url_generation_test.rb | 3 +- railties/test/isolation/abstract_unit.rb | 2 +- 17 files changed, 74 insertions(+), 67 deletions(-) diff --git a/actionpack/lib/action_controller/deprecated/base.rb b/actionpack/lib/action_controller/deprecated/base.rb index 7aa2a34d37..34f8f4a822 100644 --- a/actionpack/lib/action_controller/deprecated/base.rb +++ b/actionpack/lib/action_controller/deprecated/base.rb @@ -78,10 +78,23 @@ module ActionController Rails.application.config.action_dispatch.ip_spoofing_check = value end + def session(*args) + ActiveSupport::Deprecation.warn( + "Disabling sessions for a single controller has been deprecated. " + + "Sessions are now lazy loaded. So if you don't access them, " + + "consider them off. You can still modify the session cookie " + + "options with request.session_options.", caller) + end + def session=(value) ActiveSupport::Deprecation.warn "ActionController::Base.session= is deprecated. " << - "Please configure it on your application with config.action_dispatch.session=", caller - Rails.application.config.action_dispatch.session = value.delete(:disabled) ? nil : value + "Please configure it on your application with config.session_store :cookie_store, :key => '....'", caller + if value.delete(:disabled) + Rails.application.config.session_store :disabled + else + store = Rails.application.config.session_store + Rails.application.config.session_store store, value + end end # Controls the resource action separator diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index afa7674e40..f1355a83a3 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -165,7 +165,7 @@ module ActionController # Authenticate with HTTP Digest, returns true or false def authenticate_with_http_digest(realm = "Application", &password_procedure) - HttpAuthentication::Digest.authenticate(config.session_options[:secret], request, realm, &password_procedure) + HttpAuthentication::Digest.authenticate(config.secret, request, realm, &password_procedure) end # Render output including the HTTP Digest authentication header @@ -238,7 +238,7 @@ module ActionController end def authentication_header(controller, realm) - secret_key = controller.config.session_options[:secret] + secret_key = controller.config.secret nonce = self.nonce(secret_key) opaque = opaque(secret_key) controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce}", opaque="#{opaque}") diff --git a/actionpack/lib/action_controller/metal/session_management.rb b/actionpack/lib/action_controller/metal/session_management.rb index 1ea22b7b28..91d89ff9a4 100644 --- a/actionpack/lib/action_controller/metal/session_management.rb +++ b/actionpack/lib/action_controller/metal/session_management.rb @@ -2,38 +2,8 @@ module ActionController #:nodoc: module SessionManagement #:nodoc: extend ActiveSupport::Concern - included do - # This is still needed for the session secret for some reason. - self.config.session_options ||= {} - end - - def self.session_store_for(store) - case store - when :active_record_store - ActiveRecord::SessionStore - when Symbol - ActionDispatch::Session.const_get(store.to_s.camelize) - else - store - end - end - module ClassMethods - def session_options - config.session_options - end - def session_store - SessionManagement.session_store_for(config.session_store) - end - - def session(*args) - ActiveSupport::Deprecation.warn( - "Disabling sessions for a single controller has been deprecated. " + - "Sessions are now lazy loaded. So if you don't access them, " + - "consider them off. You can still modify the session cookie " + - "options with request.session_options.", caller) - end end end end diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index 031df9423f..e9edf80451 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -49,11 +49,9 @@ module ActionController ac.assets_dir = paths.public.to_a.first ac.javascripts_dir = paths.public.javascripts.to_a.first ac.stylesheets_dir = paths.public.stylesheets.to_a.first + ac.secret = app.config.cookie_secret ActionController::Base.config.replace(ac) - # app.config.action_controller.each do |k,v| - # ActionController::Base.send "#{k}=", v - # end end initializer "action_controller.initialize_framework_caches" do diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 04a101dbb2..db64711052 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -177,9 +177,8 @@ module ActionDispatch if key.blank? raise ArgumentError, 'A key is required to write a ' + 'cookie containing the session data. Use ' + - 'config.action_controller.session = { :key => ' + - '"_myapp_session", :secret => "some secret phrase" } in ' + - 'config/application.rb' + 'config.action_controller.session_store :cookie_store, { :key => ' + + '"_myapp_session" } in config/application.rb' end end @@ -193,10 +192,9 @@ module ActionDispatch if secret.blank? raise ArgumentError, "A secret is required to generate an " + "integrity hash for cookie session data. Use " + - "config.action_controller.session = { :key => " + - "\"_myapp_session\", :secret => \"some secret phrase of at " + - "least #{SECRET_MIN_LENGTH} characters\" } " + - "in config/environment.rb" + "config.cookie_secret = \"some secret phrase of at " + + "least #{SECRET_MIN_LENGTH} characters\"" + + "in config/application.rb" end if secret.length < SECRET_MIN_LENGTH diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 30b3535e17..e486bd4079 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -7,8 +7,6 @@ module ActionDispatch config.action_dispatch.x_sendfile_header = "X-Sendfile" config.action_dispatch.ip_spoofing_check = true - config.action_dispatch.session = {} - config.action_dispatch.session_store = :cookie_store # Prepare dispatcher callbacks and run 'prepare' callbacks initializer "action_dispatch.prepare_dispatcher" do |app| diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 29270ed228..d103c4e485 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -170,8 +170,7 @@ end # Temporary base class class Rack::TestCase < ActionController::IntegrationTest setup do - ActionController::Base.session_options[:key] = "abc" - ActionController::Base.session_options[:secret] = ("*" * 30) + ActionController::Base.config.secret = "abc" * 30 end def self.testing(klass = nil) diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 6f167fe627..eb2af523a2 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -41,11 +41,12 @@ class HttpDigestAuthenticationTest < ActionController::TestCase setup do # Used as secret in generating nonce to prevent tampering of timestamp @secret = "session_options_secret" - @old_secret, ActionController::Base.session_options[:secret] = ActionController::Base.session_options[:secret], @secret + @controller.config.secret = @secret + # @old_secret, ActionController::Base.config.secret[:secret] = ActionController::Base.session_options[:secret], @secret end teardown do - ActionController::Base.session_options[:secret] = @old_secret + # ActionController::Base.session_options[:secret] = @old_secret end AUTH_HEADERS.each do |header| diff --git a/railties/lib/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt b/railties/lib/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt index 451dbe1d1c..be627fbbcc 100644 --- a/railties/lib/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt +++ b/railties/lib/generators/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt @@ -4,4 +4,4 @@ # If you change this key, all old signed cookies will become invalid! # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -ActionController::Base.cookie_verifier_secret = '<%= app_secret %>' +Rails.application.config.cookie_secret = '<%= app_secret %>' diff --git a/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt b/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt index 2f04ed8fb0..edd2273fb0 100644 --- a/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt +++ b/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt @@ -1,12 +1,7 @@ # Be sure to restart your server when you modify this file. -# Your secret key for verifying cookie session data integrity. -# If you change this key, all old sessions will become invalid! -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -Rails.application.config.action_dispatch.session = { - :key => '_<%= app_name %>_session', - :secret => '<%= app_secret %>' +Rails.application.config.session_store :cookie_store, { + :key => '_<%= app_name %>_session', } # Use the database for sessions instead of the cookie-based default, diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 5d3e768cfd..cdaf35542f 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -7,6 +7,7 @@ module Rails attr_writer :eager_load_paths, :load_once_paths, :load_paths def initialize(root=nil) + super() @root = root end diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb index 28d7b2f9ae..6a8c4ca09f 100644 --- a/railties/lib/rails/railtie/configuration.rb +++ b/railties/lib/rails/railtie/configuration.rb @@ -3,6 +3,13 @@ require 'rails/configuration' module Rails class Railtie class Configuration + attr_accessor :cookie_secret + + def initialize + @session_store = :cookie_store + @session_options = {} + end + def middleware @@default_middleware_stack ||= default_middleware end @@ -52,6 +59,24 @@ module Rails @metal_loader ||= Rails::Application::MetalLoader.new end + def session_store(*args) + if args.empty? + case @session_store + when :disabled + nil + when :active_record_store + ActiveRecord::SessionStore + when Symbol + ActionDispatch::Session.const_get(@session_store.to_s.camelize) + else + @session_store + end + else + @session_store = args.shift + @session_options = args.shift || {} + end + end + private def method_missing(name, *args, &blk) @@ -61,6 +86,11 @@ module Rails super end + def session_options + return @session_options unless @session_store == :cookie_store + @session_options.merge(:secret => @cookie_secret) + end + def config_key_regexp bits = config_keys.map { |n| Regexp.escape(n.to_s) }.join('|') /^(#{bits})(?:=)?$/ @@ -86,8 +116,8 @@ module Rails middleware.use('::Rack::Sendfile', lambda { action_dispatch.x_sendfile_header }) middleware.use('::ActionDispatch::Callbacks', lambda { !cache_classes }) middleware.use('::ActionDispatch::Cookies') - middleware.use(lambda { ActionController::SessionManagement.session_store_for(action_dispatch.session_store) }, lambda { action_dispatch.session }) - middleware.use('::ActionDispatch::Flash', :if => lambda { action_dispatch.session_store }) + middleware.use(lambda { session_store }, lambda { session_options }) + middleware.use('::ActionDispatch::Flash', :if => lambda { session_store }) middleware.use(lambda { metal_loader.build_middleware(metals) }, :if => lambda { metal_loader.metals.any? }) middleware.use('ActionDispatch::ParamsParser') middleware.use('::Rack::MethodOverride') diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 25389c86f7..54cd751f4e 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -177,7 +177,8 @@ module ApplicationTests require "action_controller/railtie" class MyApp < Rails::Application - config.action_dispatch.session = { :key => "_myapp_session", :secret => "3b7cd727ee24e8444053437c36cc66c4" } + config.cookie_secret = "3b7cd727ee24e8444053437c36cc66c4" + config.session_store :cookie_store, :key => "_myapp_session" end MyApp.initialize! @@ -204,7 +205,8 @@ module ApplicationTests require "action_controller/railtie" class MyApp < Rails::Application - config.action_dispatch.session = { :key => "_myapp_session", :secret => "3b7cd727ee24e8444053437c36cc66c4" } + config.cookie_secret = "3b7cd727ee24e8444053437c36cc66c4" + config.session_store :cookie_store, :key => "_myapp_session" config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File' end diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index d74de3d666..8e57022e5b 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -65,7 +65,7 @@ module ApplicationTests test "database middleware doesn't initialize when session store is not active_record" do add_to_config <<-RUBY config.root = "#{app_path}" - config.action_dispatch.session_store = :cookie_store + config.session_store :cookie_store, { :key => "blahblahblah" } RUBY require "#{app_path}/config/environment" @@ -73,7 +73,7 @@ module ApplicationTests end test "database middleware initializes when session store is active record" do - add_to_config "config.action_dispatch.session_store = :active_record_store" + add_to_config "config.session_store :active_record_store" require "#{app_path}/config/environment" diff --git a/railties/test/application/middleware_stack_defaults_test.rb b/railties/test/application/middleware_stack_defaults_test.rb index 9086ddcfe7..284f7e2e5b 100644 --- a/railties/test/application/middleware_stack_defaults_test.rb +++ b/railties/test/application/middleware_stack_defaults_test.rb @@ -10,7 +10,8 @@ class MiddlewareStackDefaultsTest < Test::Unit::TestCase Object.const_set(:MyApplication, Class.new(Rails::Application)) MyApplication.class_eval do - config.action_dispatch.session = { :key => "_myapp_session", :secret => "OMG A SEKRET" * 10 } + config.cookie_secret = "3b7cd727ee24e8444053437c36cc66c4" + config.session_store :cookie_store, :key => "_myapp_session" end end diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb index f8e9a39969..04f5454e09 100644 --- a/railties/test/application/url_generation_test.rb +++ b/railties/test/application/url_generation_test.rb @@ -14,7 +14,8 @@ module ApplicationTests require "action_controller/railtie" class MyApp < Rails::Application - config.action_dispatch.session = { :key => "_myapp_session", :secret => "3b7cd727ee24e8444053437c36cc66c4" } + config.cookie_secret = "3b7cd727ee24e8444053437c36cc66c4" + config.session_store :cookie_store, :key => "_myapp_session" end MyApp.initialize! diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 2b0d5a8ba0..8f2f15b49e 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -100,7 +100,7 @@ module TestHelpers end end - add_to_config 'config.action_dispatch.session = { :key => "_myapp_session", :secret => "bac838a849c1d5c4de2e6a50af826079" }' + add_to_config 'config.cookie_secret = "3b7cd727ee24e8444053437c36cc66c4"; config.session_store :cookie_store, :key => "_myapp_session"' end class Bukkit