Skip to content

Commit 5106ce8

Browse files
Jakub Kuźmajeremy
Jakub Kuźma
authored andcommitted
authenticity_token option for form_tag [#2988 state:resolved]
1 parent 5d1d9bf commit 5106ce8

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

actionpack/CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
*Rails 3.1.0 (unreleased)*
22

3+
* 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]
4+
35
* HTML5 button_tag helper. [Rizwan Reza]
46

57
* Template lookup now searches further up in the inheritance chain. [Artemave]

actionpack/lib/action_view/helpers/form_tag_helper.rb

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ module FormTagHelper
2525
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
2626
# If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
2727
# is added to simulate the verb over post.
28+
# * <tt>:authenticity_token</tt> - Authenticity token to use in the form. Use only if you need to
29+
# pass custom authenticity token string, or to not add authenticity_token field at all
30+
# (by passing <tt>false</tt>).
2831
# * A list of parameters to feed to the URL the form will be posted to.
2932
# * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
3033
# submit behaviour. By default this behaviour is an ajax submit.
@@ -47,6 +50,12 @@ module FormTagHelper
4750
# <%= form_tag('/posts', :remote => true) %>
4851
# # => <form action="/posts" method="post" data-remote="true">
4952
#
53+
# form_tag('http://far.away.com/form', :authenticity_token => false)
54+
# # form without authenticity token
55+
#
56+
# form_tag('http://far.away.com/form', :authenticity_token => "cf50faa3fe97702ca1ae")
57+
# # form with custom authenticity token
58+
#
5059
def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)
5160
html_options = html_options_for_form(url_for_options, options, *parameters_for_url)
5261
if block_given?
@@ -584,13 +593,15 @@ def html_options_for_form(url_for_options, options, *parameters_for_url)
584593
html_options["action"] = url_for(url_for_options, *parameters_for_url)
585594
html_options["accept-charset"] = "UTF-8"
586595
html_options["data-remote"] = true if html_options.delete("remote")
596+
html_options["authenticity_token"] = html_options.delete("authenticity_token") if html_options.has_key?("authenticity_token")
587597
end
588598
end
589599

590600
def extra_tags_for_form(html_options)
591601
snowman_tag = tag(:input, :type => "hidden",
592602
:name => "utf8", :value => "&#x2713;".html_safe)
593603

604+
authenticity_token = html_options.delete("authenticity_token")
594605
method = html_options.delete("method").to_s
595606

596607
method_tag = case method
@@ -599,10 +610,10 @@ def extra_tags_for_form(html_options)
599610
''
600611
when /^post$/i, "", nil
601612
html_options["method"] = "post"
602-
token_tag
613+
token_tag(authenticity_token)
603614
else
604615
html_options["method"] = "post"
605-
tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag
616+
tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag(authenticity_token)
606617
end
607618

608619
tags = snowman_tag << method_tag
@@ -622,11 +633,12 @@ def form_tag_in_block(html_options, &block)
622633
output.safe_concat("</form>")
623634
end
624635

625-
def token_tag
626-
unless protect_against_forgery?
636+
def token_tag(token)
637+
if token == false || !protect_against_forgery?
627638
''
628639
else
629-
tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
640+
token = form_authenticity_token if token.nil?
641+
tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => token)
630642
end
631643
end
632644

actionpack/test/controller/request_forgery_protection_test.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ def show_button
1212
render :inline => "<%= button_to('New', '/') {} %>"
1313
end
1414

15+
def external_form
16+
render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => 'external_token') {} %>"
17+
end
18+
19+
def external_form_without_protection
20+
render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => false) {} %>"
21+
end
22+
1523
def unsafe
1624
render :text => 'pwn'
1725
end
@@ -65,6 +73,16 @@ def test_should_render_button_to_with_token_tag
6573
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
6674
end
6775

76+
def test_should_render_external_form_with_external_token
77+
get :external_form
78+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', 'external_token'
79+
end
80+
81+
def test_should_render_external_form_without_token
82+
get :external_form_without_protection
83+
assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
84+
end
85+
6886
def test_should_allow_get
6987
get :index
7088
assert_response :success

0 commit comments

Comments
 (0)