Skip to content
This repository
Browse code

configure how unverified request will be handled

can be configured using `:with` option in `protect_from_forgery` method
or `request_forgery_protection_method` config option

possible values:
- :reset_session (default)
- :exception

new applications are generated with:

    protect_from_forgery :with => :exception
  • Loading branch information...
commit 245941101b1ea00a9b1af613c20b0ee994a43946 1 parent 7638004
Sergey Nartimov authored March 09, 2012
20  actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -37,6 +37,10 @@ module RequestForgeryProtection
37 37
       config_accessor :request_forgery_protection_token
38 38
       self.request_forgery_protection_token ||= :authenticity_token
39 39
 
  40
+      # Controls how unverified request will be handled
  41
+      config_accessor :request_forgery_protection_method
  42
+      self.request_forgery_protection_method ||= :reset_session
  43
+
40 44
       # Controls whether request forgery protection is turned on or not. Turned off by default only in test mode.
41 45
       config_accessor :allow_forgery_protection
42 46
       self.allow_forgery_protection = true if allow_forgery_protection.nil?
@@ -64,8 +68,10 @@ module ClassMethods
64 68
       # Valid Options:
65 69
       #
66 70
       # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
  71
+      # * <tt>:with</tt> - Set the method to handle unverified request. Valid values: <tt>:exception</tt> and <tt>:reset_session</tt> (default).
67 72
       def protect_from_forgery(options = {})
68 73
         self.request_forgery_protection_token ||= :authenticity_token
  74
+        self.request_forgery_protection_method = options.delete(:with) if options.key?(:with)
69 75
         prepend_before_filter :verify_authenticity_token, options
70 76
       end
71 77
     end
@@ -80,9 +86,19 @@ def verify_authenticity_token
80 86
       end
81 87
 
82 88
       # This is the method that defines the application behavior when a request is found to be unverified.
83  
-      # By default, \Rails resets the session when it finds an unverified request.
  89
+      # By default, \Rails uses <tt>request_forgery_protection_method</tt> when it finds an unverified request:
  90
+      #
  91
+      # * <tt>:reset_session</tt> - Resets the session.
  92
+      # * <tt>:exception</tt>: - Raises ActionController::InvalidAuthenticityToken exception.
84 93
       def handle_unverified_request
85  
-        reset_session
  94
+        case request_forgery_protection_method
  95
+        when :exception
  96
+          raise ActionController::InvalidAuthenticityToken
  97
+        when :reset_session
  98
+          reset_session
  99
+        else
  100
+          raise ArgumentError, 'Invalid request forgery protection method, use :exception or :reset_session'
  101
+        end
86 102
       end
87 103
 
88 104
       # Returns true or false if a request is verified. Checks:
4  actionpack/test/controller/request_forgery_protection_test.rb
@@ -43,7 +43,7 @@ class RequestForgeryProtectionController < ActionController::Base
43 43
   protect_from_forgery :only => %w(index meta)
44 44
 end
45 45
 
46  
-class RequestForgeryProtectionControllerUsingOldBehaviour < ActionController::Base
  46
+class RequestForgeryProtectionControllerUsingException < ActionController::Base
47 47
   include RequestForgeryProtectionActions
48 48
   protect_from_forgery :only => %w(index meta)
49 49
 
@@ -215,7 +215,7 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase
215 215
   end
216 216
 end
217 217
 
218  
-class RequestForgeryProtectionControllerUsingOldBehaviourTest < ActionController::TestCase
  218
+class RequestForgeryProtectionControllerUsingExceptionTest < ActionController::TestCase
219 219
   include RequestForgeryProtectionTests
220 220
   def assert_blocked
221 221
     assert_raises(ActionController::InvalidAuthenticityToken) do
4  railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb
... ...
@@ -1,3 +1,5 @@
1 1
 class ApplicationController < ActionController::Base
2  
-  protect_from_forgery
  2
+  # prevent CSRF attacks by raising an exception,
  3
+  # if your application has an API, you'll probably need to use :reset_session
  4
+  protect_from_forgery :with => :exception
3 5
 end
18  railties/test/application/configuration_test.rb
@@ -275,19 +275,23 @@ def update
275 275
 
276 276
       require "#{app_path}/config/environment"
277 277
 
  278
+      token = "cf50faa3fe97702ca1ae"
  279
+      PostsController.any_instance.stubs(:form_authenticity_token).returns(token)
  280
+      params = {:authenticity_token => token}
  281
+
278 282
       get "/posts/1"
279 283
       assert_match /patch/, last_response.body
280 284
 
281  
-      patch "/posts/1"
  285
+      patch "/posts/1", params
282 286
       assert_match /update/, last_response.body
283 287
 
284  
-      patch "/posts/1"
  288
+      patch "/posts/1", params
285 289
       assert_equal 200, last_response.status
286 290
 
287  
-      put "/posts/1"
  291
+      put "/posts/1", params
288 292
       assert_match /update/, last_response.body
289 293
 
290  
-      put "/posts/1"
  294
+      put "/posts/1", params
291 295
       assert_equal 200, last_response.status
292 296
     end
293 297
 
@@ -528,6 +532,12 @@ def self.attribute_names
528 532
       end
529 533
       RUBY
530 534
 
  535
+      app_file 'app/controllers/application_controller.rb', <<-RUBY
  536
+      class ApplicationController < ActionController::Base
  537
+        protect_from_forgery :with => :reset_session # as we are testing API here
  538
+      end
  539
+      RUBY
  540
+
531 541
       app_file 'app/controllers/posts_controller.rb', <<-RUBY
532 542
       class PostsController < ApplicationController
533 543
         def create

0 notes on commit 2459411

Please sign in to comment.
Something went wrong with that request. Please try again.