Permalink
Browse files

Deprecated ActionController::Base.session_options= and ActionControll…

…er::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.
  • Loading branch information...
Carlhuda
Carlhuda committed Mar 4, 2010
1 parent 48bb3b3 commit e311622e7b20b3fdeab6a93418c8a45c6e7137b6
@@ -78,10 +78,23 @@ def trusted_proxies
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
@@ -165,7 +165,7 @@ def authenticate_or_request_with_http_digest(realm = "Application", &password_pr
# 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 @@ def decode_credentials(header)
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}")
@@ -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
@@ -49,11 +49,9 @@ class Railtie < Rails::Railtie
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
@@ -177,9 +177,8 @@ def ensure_session_key(key)
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 @@ def ensure_secret_secure(secret)
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
@@ -7,8 +7,6 @@ class Railtie < Rails::Railtie
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|
@@ -170,8 +170,7 @@ def with_routing(&block)
# 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)
@@ -41,11 +41,12 @@ def authenticate_with_request
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|
@@ -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 %>'
@@ -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,
@@ -7,6 +7,7 @@ class Configuration < ::Rails::Railtie::Configuration
attr_writer :eager_load_paths, :load_once_paths, :load_paths
def initialize(root=nil)
+ super()
@root = root
end
@@ -3,6 +3,13 @@
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 @@ def metal_loader
@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 @@ def method_missing(name, *args, &blk)
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 @@ def default_middleware
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')
@@ -177,7 +177,8 @@ def teardown
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 @@ def index
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
@@ -65,15 +65,15 @@ def setup
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"
assert !Rails.application.config.middleware.include?(ActiveRecord::SessionStore)
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"
@@ -10,7 +10,8 @@ def setup
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
@@ -14,7 +14,8 @@ def app
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!
@@ -100,7 +100,7 @@ def build_app(options = {})
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

3 comments on commit e311622

@josh

This comment has been minimized.

Show comment Hide comment
@josh

josh Mar 5, 2010

Member

I don't think "cookie_secret" should be a first class option.

Unless, that is, we call it something more generic like "secret_token" which is something various things can hook into. I don't see the purpose of having both a "cookie secret" and a "session secret".

Member

josh replied Mar 5, 2010

I don't think "cookie_secret" should be a first class option.

Unless, that is, we call it something more generic like "secret_token" which is something various things can hook into. I don't see the purpose of having both a "cookie secret" and a "session secret".

@jeremy

This comment has been minimized.

Show comment Hide comment
@jeremy

jeremy Mar 5, 2010

Owner

Session secret is now unneeded since it'll just use cookie signing. I could see having a global key, but that means changing your key invalidates all your signed messages, rather than just your cookies.

Owner

jeremy replied Mar 5, 2010

Session secret is now unneeded since it'll just use cookie signing. I could see having a global key, but that means changing your key invalidates all your signed messages, rather than just your cookies.

@jpartogi

This comment has been minimized.

Show comment Hide comment
@jpartogi

jpartogi Apr 3, 2010

How do we suppose to get session_options now?

How do we suppose to get session_options now?

Please sign in to comment.