1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add controller-specific force_ssl method to force web browser to use HTTPS protocol

This would become useful for site which sometime transferring sensitive information such as account information on particular controller or action.

This featured was requested by DHH.
This commit is contained in:
Prem Sichanugrist 2011-03-28 03:05:14 +08:00 committed by David Heinemeier Hansson
parent 84aab7aa53
commit 7cbdfa8303
6 changed files with 144 additions and 0 deletions

View file

@ -1,5 +1,7 @@
*Rails 3.1.0 (unreleased)*
* Allow you to add `force_ssl` into controller to force browser to transfer data via HTTPS protocol on that particular controller. You can also specify `:only` or `:except` to specific it to particular action. [DHH and Prem Sichanugrist]
* Allow FormHelper#form_for to specify the :method as a direct option instead of through the :html hash [DHH]
form_for(@post, remote: true, method: :delete) instead of form_for(@post, remote: true, html: { method: :delete })

View file

@ -14,6 +14,7 @@ module ActionController
autoload :ConditionalGet
autoload :Cookies
autoload :Flash
autoload :ForceSSL
autoload :Head
autoload :Helpers
autoload :HideActions

View file

@ -198,6 +198,7 @@ module ActionController
Cookies,
Flash,
RequestForgeryProtection,
ForceSSL,
Streaming,
RecordIdentifier,
HttpAuthentication::Basic::ControllerMethods,

View file

@ -0,0 +1,35 @@
module ActionController
# This module provides a method which will redirects browser to use HTTPS
# protocol. This will ensure that user's sensitive information will be
# transferred safely over the internet. You _should_ always force browser
# to use HTTPS when you're transferring sensitive information such as
# user authentication, account information, or credit card information.
#
# Note that if you really concern about your application safety, you might
# consider using +config.force_ssl+ in your configuration config file instead.
# That will ensure all the data transferred via HTTPS protocol and prevent
# user from getting session hijacked when accessing the site under unsecured
# HTTP protocol.
module ForceSSL
extend ActiveSupport::Concern
include AbstractController::Callbacks
module ClassMethods
# Force the request to this particular controller or specified actions to be
# under HTTPS protocol.
#
# Note that this method will not be effective on development environment.
#
# ==== Options
# * <tt>only</tt> - The callback should be run only for this action
# * <tt>except<tt> - The callback should be run for all actions except this action
def force_ssl(options = {})
before_filter(options) do
if !request.ssl? && !Rails.env.development?
redirect_to :protocol => 'https://', :status => :moved_permanently
end
end
end
end
end
end

View file

@ -0,0 +1,83 @@
require 'abstract_unit'
class ForceSSLController < ActionController::Base
def banana
render :text => "monkey"
end
def cheeseburger
render :text => "sikachu"
end
end
class ForceSSLControllerLevel < ForceSSLController
force_ssl
end
class ForceSSLOnlyAction < ForceSSLController
force_ssl :only => :cheeseburger
end
class ForceSSLExceptAction < ForceSSLController
force_ssl :except => :banana
end
class ForceSSLControllerLevelTest < ActionController::TestCase
tests ForceSSLControllerLevel
def test_banana_redirects_to_https
get :banana
assert_response 301
assert_equal "https://test.host/force_ssl_controller_level/banana", redirect_to_url
end
def test_cheeseburger_redirects_to_https
get :cheeseburger
assert_response 301
assert_equal "https://test.host/force_ssl_controller_level/cheeseburger", redirect_to_url
end
end
class ForceSSLOnlyActionTest < ActionController::TestCase
tests ForceSSLOnlyAction
def test_banana_not_redirects_to_https
get :banana
assert_response 200
end
def test_cheeseburger_redirects_to_https
get :cheeseburger
assert_response 301
assert_equal "https://test.host/force_ssl_only_action/cheeseburger", redirect_to_url
end
end
class ForceSSLExceptActionTest < ActionController::TestCase
tests ForceSSLExceptAction
def test_banana_not_redirects_to_https
get :banana
assert_response 200
end
def test_cheeseburger_redirects_to_https
get :cheeseburger
assert_response 301
assert_equal "https://test.host/force_ssl_except_action/cheeseburger", redirect_to_url
end
end
class ForceSSLExcludeDevelopmentTest < ActionController::TestCase
tests ForceSSLControllerLevel
def setup
Rails.env.stubs(:development?).returns(false)
end
def test_development_environment_not_redirects_to_https
Rails.env.stubs(:development?).returns(true)
get :banana
assert_response 200
end
end

View file

@ -816,6 +816,28 @@ end
NOTE: Certain exceptions are only rescuable from the +ApplicationController+ class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik's "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information.
h3. Force HTTPS protocol
Sometime you might want to force a particular controller to only be accessible via an HTTPS protocol for security reason. Since Rails 3.1 you can now use +force_ssl+ method in your controller to enforce that:
<ruby>
class DinnerController
force_ssl
end
</ruby>
Just like the filter, you could also passing +:only+ and +:except+ to enforce the secure connection only to specific actions
<ruby>
class DinnerController
force_ssl :only => :cheeseburger
# or
force_ssl :except => :cheeseburger
end
</ruby>
Please note that if you found yourself adding +force_ssl+ to many controllers, you may found yourself wanting to force the whole application to use HTTPS instead. In that case, you can set the +config.force_ssl+ in your environment file.
h3. Changelog
* February 17, 2009: Yet another proofread by Xavier Noria.