From 2c0c4d754e34b13379dfc53121a970c25fab5dae Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Sun, 27 Mar 2011 23:55:46 +0700 Subject: Add `config.force_ssl` configuration which will load `Rack::SSL` middleware if set to true This will allow user to be able to force all requests to be under HTTPS protocol. This commit was a request from DHH. Special thanks to Josh Peek as well for making `Rack::SSL`. --- railties/CHANGELOG | 2 ++ railties/guides/source/configuring.textile | 3 +++ railties/guides/source/security.textile | 6 +++++- railties/lib/rails/application.rb | 17 +++++++++++++---- railties/lib/rails/application/configuration.rb | 3 ++- .../templates/config/environments/development.rb.tt | 2 +- .../app/templates/config/environments/production.rb.tt | 18 +++++++----------- railties/railties.gemspec | 1 + railties/test/application/middleware_test.rb | 6 ++++++ 9 files changed, 40 insertions(+), 18 deletions(-) (limited to 'railties') diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 75f1df44e7..c1e0a214d2 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* Added `config.force_ssl` configuration which loads Rack::SSL middleware and force all requests to be under HTTPS protocol [DHH, Prem Sichanugrist, and Josh Peek] + * Added `rails plugin new` command which generates rails plugin with gemspec, tests and dummy application for testing [Piotr Sarnacki] * Added -j parameter with jquery/prototype as options. Now you can create your apps with jQuery using `rails new myapp -j jquery`. The default is still Prototype. [siong1987] diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile index 62b846e871..04e2d6daed 100644 --- a/railties/guides/source/configuring.textile +++ b/railties/guides/source/configuring.textile @@ -81,6 +81,8 @@ end * +config.filter_parameters+ used for filtering out the parameters that you don't want shown in the logs, such as passwords or credit card numbers. +* +config.force_ssl+ forcing all requests to be under HTTPS protocol by using +Rack::SSL+ middleware. This will secure your application from a session hijack attempt. + * +config.helper_paths+ configures where Rails can find helpers for this application. * +config.log_level+ defines the verbosity of the Rails logger. In production mode, this defaults to +:info+. In development mode, it defaults to +:debug+. @@ -147,6 +149,7 @@ h4. Configuring Middleware Every Rails application comes with a standard set of middleware which it uses in this order in the development environment: +* +Rack::SSL+ Will force every requests to be under HTTPS protocal. Will be available if +config.force_ssl+ is set to _true_. * +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_. * +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default. * +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread. diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index 182f3631ef..893f65856c 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -57,7 +57,11 @@ Many web applications have an authentication system: a user provides a user name Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures: -* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_. +* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file: + + +config.force_ssl = true + * Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a _(highlight)log-out button_ in the web application, and _(highlight)make it prominent_. diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 94819820bc..1b834275a7 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -145,15 +145,21 @@ module Rails def default_middleware_stack ActionDispatch::MiddlewareStack.new.tap do |middleware| - rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache + if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache + require "action_dispatch/http/rack_cache" + middleware.use ::Rack::Cache, rack_cache + end - require "action_dispatch/http/rack_cache" if rack_cache - middleware.use ::Rack::Cache, rack_cache if rack_cache + if config.force_ssl + require "rack/ssl" + middleware.use ::Rack::SSL + end if config.serve_static_assets asset_paths = ActiveSupport::OrderedHash[config.static_asset_paths.to_a.reverse] middleware.use ::ActionDispatch::Static, asset_paths end + middleware.use ::Rack::Lock unless config.allow_concurrency middleware.use ::Rack::Runtime middleware.use ::Rails::Rack::Logger @@ -174,7 +180,10 @@ module Rails middleware.use ::ActionDispatch::Head middleware.use ::Rack::ConditionalGet middleware.use ::Rack::ETag, "no-cache" - middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support if config.action_dispatch.best_standards_support + + if config.action_dispatch.best_standards_support + middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support + end end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index c74bcbedf2..23b0e765ae 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -9,7 +9,7 @@ module Rails :filter_parameters, :helpers_paths, :logger, :preload_frameworks, :reload_plugins, :secret_token, :serve_static_assets, :session_options, - :time_zone, :whiny_nils + :time_zone, :whiny_nils, :force_ssl attr_writer :log_level @@ -22,6 +22,7 @@ module Rails @helpers_paths = [] @dependency_loading = true @serve_static_assets = true + @force_ssl = false @session_store = :cookie_store @session_options = {} @time_zone = "UTC" diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index 91d3133ea4..bdb897ad33 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -3,7 +3,7 @@ # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development - # since you don't have to restart the webserver when you make code changes. + # since you don't have to restart the web server when you make code changes. config.cache_classes = false # Log error messages when you accidentally call methods on nil. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 89bb891ddd..874cc403ba 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -1,7 +1,6 @@ <%= app_const %>.configure do # Settings specified here will take precedence over those in config/application.rb - # The production environment is meant for finished, "live" apps. # Code is not reloaded between requests config.cache_classes = true @@ -9,14 +8,15 @@ config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Specifies the header that your server uses for sending files - config.action_dispatch.x_sendfile_header = "X-Sendfile" + # Disable Rails's static asset server (Apache or nginx will already do this) + config.serve_static_assets = false - # For nginx: - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' + # Specifies the header that your server uses for sending files + # (comment out if your front-end server doesn't support this) + config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx - # If you have no front-end server that supports something like X-Sendfile, - # just comment this out and Rails will serve the files + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true # See everything in the log (default is :info) # config.log_level = :debug @@ -27,10 +27,6 @@ # Use a different cache store in production # config.cache_store = :mem_cache_store - # Disable Rails's static asset server - # In production, Apache or nginx will already do this - config.serve_static_assets = false - # Enable serving of images, stylesheets, and javascripts from an asset server # config.action_controller.asset_host = "http://assets.example.com" diff --git a/railties/railties.gemspec b/railties/railties.gemspec index c3793d3ac3..c51fe856be 100644 --- a/railties/railties.gemspec +++ b/railties/railties.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.add_dependency('rake', '>= 0.8.7') s.add_dependency('thor', '~> 0.14.4') + s.add_dependency('rack-ssl', '~> 1.3.2') s.add_dependency('activesupport', version) s.add_dependency('actionpack', version) end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index b314832685..0df6f33e8c 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -52,6 +52,12 @@ module ApplicationTests assert_equal "Rack::Cache", middleware.first end + test "Rack::SSL is present with force_ssl is set" do + add_to_config "config.force_ssl = true" + boot! + assert middleware.include?("Rack::SSL") + end + test "removing Active Record omits its middleware" do use_frameworks [] boot! -- cgit v1.2.3