From 5106ce88e44286b88e5c2e2c261deb7e28392994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ku=C5=BAma?= Date: Mon, 27 Dec 2010 23:31:14 +0100 Subject: authenticity_token option for form_tag [#2988 state:resolved] --- actionpack/CHANGELOG | 2 ++ .../lib/action_view/helpers/form_tag_helper.rb | 22 +++++++++++++++++----- .../controller/request_forgery_protection_test.rb | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 0687187904..ee9d30e1fb 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* Add an :authenticity_token option to form_tag for custom handling or to omit the token (pass :authenticity_token => false). [Jakub Kuźma, Igor Wiedler] + * HTML5 button_tag helper. [Rizwan Reza] * Template lookup now searches further up in the inheritance chain. [Artemave] diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 3daf68d29f..159b2a2b8e 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -25,6 +25,9 @@ module ActionView # * :method - The method to use when submitting the form, usually either "get" or "post". # If "put", "delete", or another verb is used, a hidden input with name _method # is added to simulate the verb over post. + # * :authenticity_token - Authenticity token to use in the form. Use only if you need to + # pass custom authenticity token string, or to not add authenticity_token field at all + # (by passing false). # * A list of parameters to feed to the URL the form will be posted to. # * :remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the # submit behaviour. By default this behaviour is an ajax submit. @@ -47,6 +50,12 @@ module ActionView # <%= form_tag('/posts', :remote => true) %> # # =>
# + # form_tag('http://far.away.com/form', :authenticity_token => false) + # # form without authenticity token + # + # form_tag('http://far.away.com/form', :authenticity_token => "cf50faa3fe97702ca1ae") + # # form with custom authenticity token + # def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block) html_options = html_options_for_form(url_for_options, options, *parameters_for_url) if block_given? @@ -584,6 +593,7 @@ module ActionView html_options["action"] = url_for(url_for_options, *parameters_for_url) html_options["accept-charset"] = "UTF-8" html_options["data-remote"] = true if html_options.delete("remote") + html_options["authenticity_token"] = html_options.delete("authenticity_token") if html_options.has_key?("authenticity_token") end end @@ -591,6 +601,7 @@ module ActionView snowman_tag = tag(:input, :type => "hidden", :name => "utf8", :value => "✓".html_safe) + authenticity_token = html_options.delete("authenticity_token") method = html_options.delete("method").to_s method_tag = case method @@ -599,10 +610,10 @@ module ActionView '' when /^post$/i, "", nil html_options["method"] = "post" - token_tag + token_tag(authenticity_token) else html_options["method"] = "post" - tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag + tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag(authenticity_token) end tags = snowman_tag << method_tag @@ -622,11 +633,12 @@ module ActionView output.safe_concat("
") end - def token_tag - unless protect_against_forgery? + def token_tag(token) + if token == false || !protect_against_forgery? '' else - tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) + token = form_authenticity_token if token.nil? + tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => token) end end diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 2c9aa6187b..405af2a650 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -12,6 +12,14 @@ module RequestForgeryProtectionActions render :inline => "<%= button_to('New', '/') {} %>" end + def external_form + render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => 'external_token') {} %>" + end + + def external_form_without_protection + render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => false) {} %>" + end + def unsafe render :text => 'pwn' end @@ -65,6 +73,16 @@ module RequestForgeryProtectionTests assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token end + def test_should_render_external_form_with_external_token + get :external_form + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', 'external_token' + end + + def test_should_render_external_form_without_token + get :external_form_without_protection + assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false + end + def test_should_allow_get get :index assert_response :success -- cgit v1.2.3