1 require 'abstract_unit'
4 ActionController
::Routing::Routes.draw
do |map
|
5 map
.connect
':controller/:action/:id'
8 # simulates cookie session store
10 def self.generate_digest(data)
11 Digest
::SHA1.hexdigest("secure")
15 # common controller actions
16 module RequestForgeryProtectionActions
18 render
:inline => "<%= form_tag('/') {} %>"
22 render
:inline => "<%= button_to('New', '/') {} %>"
26 render
:inline => "<% form_remote_tag(:url => '/') {} %>"
33 def rescue_action(e
) raise e
end
37 class RequestForgeryProtectionController
< ActionController
::Base
38 include RequestForgeryProtectionActions
39 protect_from_forgery
:only => :index, :secret => 'abc'
42 class RequestForgeryProtectionWithoutSecretController
< ActionController
::Base
43 include RequestForgeryProtectionActions
47 # no token is given, assume the cookie store is used
48 class CsrfCookieMonsterController
< ActionController
::Base
49 include RequestForgeryProtectionActions
50 protect_from_forgery
:only => :index
53 # sessions are turned off
54 class SessionOffController
< ActionController
::Base
55 protect_from_forgery
:secret => 'foobar'
57 def rescue_action(e
) raise e
end
58 include RequestForgeryProtectionActions
61 class FreeCookieController
< CsrfCookieMonsterController
62 self.allow_forgery_protection
= false
65 render
:inline => "<%= form_tag('/') {} %>"
69 render
:inline => "<%= button_to('New', '/') {} %>"
75 module RequestForgeryProtectionTests
77 ActionController
::Base.request_forgery_protection_token
= nil
81 def test_should_render_form_with_token_tag
83 assert_select
'form>div>input[name=?][value=?]', 'authenticity_token', @token
86 def test_should_render_button_to_with_token_tag
88 assert_select
'form>div>input[name=?][value=?]', 'authenticity_token', @token
91 def test_should_render_remote_form_with_only_one_token_parameter
93 assert_equal
1, @response.body
.scan(@token).size
96 def test_should_allow_get
98 assert_response
:success
101 def test_should_allow_post_without_token_on_unsafe_action
103 assert_response
:success
106 def test_should_not_allow_html_post_without_token
107 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
108 assert_raises(ActionController
::InvalidAuthenticityToken) { post
:index, :format => :html }
111 def test_should_not_allow_html_put_without_token
112 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
113 assert_raises(ActionController
::InvalidAuthenticityToken) { put
:index, :format => :html }
116 def test_should_not_allow_html_delete_without_token
117 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
118 assert_raises(ActionController
::InvalidAuthenticityToken) { delete
:index, :format => :html }
121 def test_should_allow_api_formatted_post_without_token
122 assert_nothing_raised
do
123 post
:index, :format => 'xml'
127 def test_should_not_allow_api_formatted_put_without_token
128 assert_nothing_raised
do
129 put
:index, :format => 'xml'
133 def test_should_allow_api_formatted_delete_without_token
134 assert_nothing_raised
do
135 delete
:index, :format => 'xml'
139 def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
140 assert_raises(ActionController
::InvalidAuthenticityToken) do
141 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
142 post
:index, :format => 'xml'
146 def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
147 assert_raises(ActionController
::InvalidAuthenticityToken) do
148 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
149 put
:index, :format => 'xml'
153 def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
154 assert_raises(ActionController
::InvalidAuthenticityToken) do
155 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
156 delete
:index, :format => 'xml'
160 def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
161 assert_raises(ActionController
::InvalidAuthenticityToken) do
162 @request.env['CONTENT_TYPE'] = Mime
::MULTIPART_FORM.to_s
163 post
:index, :format => 'xml'
167 def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
168 assert_raises(ActionController
::InvalidAuthenticityToken) do
169 @request.env['CONTENT_TYPE'] = Mime
::MULTIPART_FORM.to_s
170 put
:index, :format => 'xml'
174 def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
175 assert_raises(ActionController
::InvalidAuthenticityToken) do
176 @request.env['CONTENT_TYPE'] = Mime
::MULTIPART_FORM.to_s
177 delete
:index, :format => 'xml'
181 def test_should_allow_xhr_post_without_token
182 assert_nothing_raised
{ xhr
:post, :index }
184 def test_should_not_allow_xhr_post_with_html_without_token
185 @request.env['CONTENT_TYPE'] = Mime
::URL_ENCODED_FORM.to_s
186 assert_raise(ActionController
::InvalidAuthenticityToken) { xhr
:post, :index }
189 def test_should_allow_xhr_put_without_token
190 assert_nothing_raised
{ xhr
:put, :index }
193 def test_should_allow_xhr_delete_without_token
194 assert_nothing_raised
{ xhr
:delete, :index }
197 def test_should_allow_post_with_token
198 post
:index, :authenticity_token => @token
199 assert_response
:success
202 def test_should_allow_put_with_token
203 put
:index, :authenticity_token => @token
204 assert_response
:success
207 def test_should_allow_delete_with_token
208 delete
:index, :authenticity_token => @token
209 assert_response
:success
212 def test_should_allow_post_with_xml
213 @request.env['CONTENT_TYPE'] = Mime
::XML.to_s
214 post
:index, :format => 'xml'
215 assert_response
:success
218 def test_should_allow_put_with_xml
219 @request.env['CONTENT_TYPE'] = Mime
::XML.to_s
220 put
:index, :format => 'xml'
221 assert_response
:success
224 def test_should_allow_delete_with_xml
225 @request.env['CONTENT_TYPE'] = Mime
::XML.to_s
226 delete
:index, :format => 'xml'
227 assert_response
:success
231 # OK let's get our test on
233 class RequestForgeryProtectionControllerTest
< Test
::Unit::TestCase
234 include RequestForgeryProtectionTests
236 @controller = RequestForgeryProtectionController
.new
237 @request = ActionController
::TestRequest.new
238 @request.format
= :html
239 @response = ActionController
::TestResponse.new
240 class << @request.session
241 def session_id() '123' end
243 @token = OpenSSL
::HMAC.hexdigest(OpenSSL
::Digest::Digest.new('SHA1'), 'abc', '123')
244 ActionController
::Base.request_forgery_protection_token
= :authenticity_token
248 class RequestForgeryProtectionWithoutSecretControllerTest
< Test
::Unit::TestCase
250 @controller = RequestForgeryProtectionWithoutSecretController
.new
251 @request = ActionController
::TestRequest.new
252 @response = ActionController
::TestResponse.new
253 class << @request.session
254 def session_id() '123' end
256 @token = OpenSSL
::HMAC.hexdigest(OpenSSL
::Digest::Digest.new('SHA1'), 'abc', '123')
257 ActionController
::Base.request_forgery_protection_token
= :authenticity_token
260 # def test_should_raise_error_without_secret
261 # assert_raises ActionController::InvalidAuthenticityToken do
267 class CsrfCookieMonsterControllerTest
< Test
::Unit::TestCase
268 include RequestForgeryProtectionTests
270 @controller = CsrfCookieMonsterController
.new
271 @request = ActionController
::TestRequest.new
272 @response = ActionController
::TestResponse.new
273 class << @request.session
276 # simulate a cookie session store
277 @request.session
.dbman
= FakeSessionDbMan
278 @token = Digest
::SHA1.hexdigest("secure")
279 ActionController
::Base.request_forgery_protection_token
= :authenticity_token
283 class FreeCookieControllerTest
< Test
::Unit::TestCase
285 @controller = FreeCookieController
.new
286 @request = ActionController
::TestRequest.new
287 @response = ActionController
::TestResponse.new
288 @token = OpenSSL
::HMAC.hexdigest(OpenSSL
::Digest::Digest.new('SHA1'), 'abc', '123')
291 def test_should_not_render_form_with_token_tag
293 assert_select
'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
296 def test_should_not_render_button_to_with_token_tag
298 assert_select
'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
301 def test_should_allow_all_methods_without_token
302 [:post, :put, :delete].each
do |method
|
303 assert_nothing_raised
{ send(method
, :index)}
308 class SessionOffControllerTest
< Test
::Unit::TestCase
310 @controller = SessionOffController
.new
311 @request = ActionController
::TestRequest.new
312 @response = ActionController
::TestResponse.new
313 @token = OpenSSL
::HMAC.hexdigest(OpenSSL
::Digest::Digest.new('SHA1'), 'abc', '123')
316 # TODO: Rewrite this test.
317 # This test was passing but for the wrong reason.
318 # Sessions aren't really being turned off, so an exception was raised
319 # because sessions weren't on - not because the token didn't match.
321 # def test_should_raise_correct_exception
322 # @request.session = {} # session(:off) doesn't appear to work with controller tests
323 # assert_raises(ActionController::InvalidAuthenticityToken) do
324 # post :index, :authenticity_token => @token, :format => :html