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:
parent
84aab7aa53
commit
7cbdfa8303
6 changed files with 144 additions and 0 deletions
|
@ -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 })
|
||||
|
|
|
@ -14,6 +14,7 @@ module ActionController
|
|||
autoload :ConditionalGet
|
||||
autoload :Cookies
|
||||
autoload :Flash
|
||||
autoload :ForceSSL
|
||||
autoload :Head
|
||||
autoload :Helpers
|
||||
autoload :HideActions
|
||||
|
|
|
@ -198,6 +198,7 @@ module ActionController
|
|||
Cookies,
|
||||
Flash,
|
||||
RequestForgeryProtection,
|
||||
ForceSSL,
|
||||
Streaming,
|
||||
RecordIdentifier,
|
||||
HttpAuthentication::Basic::ControllerMethods,
|
||||
|
|
35
actionpack/lib/action_controller/metal/force_ssl.rb
Normal file
35
actionpack/lib/action_controller/metal/force_ssl.rb
Normal 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
|
83
actionpack/test/controller/force_ssl_test.rb
Normal file
83
actionpack/test/controller/force_ssl_test.rb
Normal 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
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue