Permalink
Browse files

change ActionController::RequestForgeryProtection to use Mime::Type#v…

…erify_request? [#73]
  • Loading branch information...
1 parent 92e2e59 commit c8451aeeea200043d8a3e6eae9c49def3a154ddb rick committed May 6, 2008
View
19 actionpack/lib/action_controller/mime_type.rb
@@ -17,6 +17,10 @@ module Mime
# end
# end
class Type
+ @@html_types = Set.new [:html, :all]
+ @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
+ cattr_reader :html_types, :unverifiable_types
+
# A simple helper class used in parsing the accept header
class AcceptItem #:nodoc:
attr_accessor :order, :name, :q
@@ -153,12 +157,21 @@ def ==(mime_type)
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
end
end
-
+
+ # Returns true if ActionPack should check requests using this Mime Type for possible request forgery. See
+ # ActionController::RequestForgerProtection.
+ def verify_request?
+ !@@unverifiable_types.include?(to_sym)
+ end
+
+ def html?
+ @@html_types.include?(to_sym) || @string =~ /html/
+ end
+
private
def method_missing(method, *args)
if method.to_s =~ /(\w+)\?$/
- mime_type = $1.downcase.to_sym
- mime_type == @symbol || (mime_type == :html && @symbol == :all)
+ $1.downcase.to_sym == to_sym
else
super
end
View
2 actionpack/lib/action_controller/mime_types.rb
@@ -17,4 +17,4 @@
Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form
# http://www.ietf.org/rfc/rfc4627.txt
-Mime::Type.register "application/json", :json, %w( text/x-json )
+Mime::Type.register "application/json", :json, %w( text/x-json )
View
2 actionpack/lib/action_controller/request_forgery_protection.rb
@@ -99,7 +99,7 @@ def verified_request?
end
def verifiable_request_format?
- request.content_type.nil? || request.content_type.html?
+ request.content_type.nil? || request.content_type.verify_request?
end
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
View
25 actionpack/test/controller/mime_type_test.rb
@@ -52,16 +52,33 @@ def test_type_should_be_equal_to_symbol
end
def test_type_convenience_methods
- types = [:html, :xml, :png, :pdf, :yaml, :url_encoded_form]
+ # Don't test Mime::ALL, since it Mime::ALL#html? == true
+ types = Mime::SET.to_a.map(&:to_sym).uniq - [:all]
+
+ # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
+ types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) }
+
types.each do |type|
mime = Mime.const_get(type.to_s.upcase)
- assert mime.send("#{type}?"), "Mime::#{type.to_s.upcase} is not #{type}?"
- (types - [type]).each { |t| assert !mime.send("#{t}?"), "Mime::#{t.to_s.upcase} is #{t}?" }
+ assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?"
+ (types - [type]).each { |other_type| assert !mime.send("#{other_type}?"), "#{mime.inspect} is #{other_type}?" }
end
end
-
+
def test_mime_all_is_html
assert Mime::ALL.all?, "Mime::ALL is not all?"
assert Mime::ALL.html?, "Mime::ALL is not html?"
end
+
+ def test_verifiable_mime_types
+ unverified_types = Mime::Type.unverifiable_types
+ all_types = Mime::SET.to_a.map(&:to_sym)
+ all_types.uniq!
+ # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
+ all_types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) }
+
+ unverified, verified = all_types.partition { |type| Mime::Type.unverifiable_types.include? type }
+ assert verified.all? { |type| Mime.const_get(type.to_s.upcase).verify_request? }, "Not all Mime Types are verified: #{verified.inspect}"
+ assert unverified.all? { |type| !Mime.const_get(type.to_s.upcase).verify_request? }, "Some Mime Types are verified: #{unverified.inspect}"
+ end
end
View
48 actionpack/test/controller/request_forgery_protection_test.rb
@@ -107,19 +107,61 @@ def test_should_not_allow_delete_without_token
end
def test_should_not_allow_api_formatted_post_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) do
+ assert_raises(ActionController::InvalidAuthenticityToken) do
post :index, :format => 'xml'
end
end
- def test_should_not_allow_put_without_token
+ def test_should_not_allow_api_formatted_put_without_token
assert_raises(ActionController::InvalidAuthenticityToken) do
put :index, :format => 'xml'
end
end
- def test_should_not_allow_delete_without_token
+ def test_should_not_allow_api_formatted_delete_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ delete :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ post :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ put :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ delete :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
+ post :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
+ assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
+ put :index, :format => 'xml'
+ end
+ end
+
+ def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
assert_raises(ActionController::InvalidAuthenticityToken) do
+ @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
delete :index, :format => 'xml'
end
end

0 comments on commit c8451ae

Please sign in to comment.