request_forgery_protection_test.rb 4.1 KB
Newer Older
1 2 3 4 5 6
require File.dirname(__FILE__) + '/../abstract_unit'

ActionController::Routing::Routes.draw do |map|
  map.connect ':controller/:action/:id'
end

7
module RequestForgeryProtectionTests
8 9 10
  def teardown
    ActionController::Base.request_forgery_protection_token = nil
  end
11
  
12 13
  def test_should_render_form_with_token_tag
    get :index
14
    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
15
  end
16 17 18 19 20
  
  def test_should_render_button_to_with_token_tag
    get :show_button
    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
  end
21 22 23 24 25 26 27 28 29 30 31 32

  def test_should_allow_get
    get :index
    assert_response :success
  end
  
  def test_should_allow_post_without_token_on_unsafe_action
    post :unsafe
    assert_response :success
  end
  
  def test_should_not_allow_post_without_token
33
    assert_raises(ActionController::InvalidAuthenticityToken) { post :index }
34 35 36
  end
  
  def test_should_not_allow_put_without_token
37
    assert_raises(ActionController::InvalidAuthenticityToken) { put :index }
38 39 40
  end
  
  def test_should_not_allow_delete_without_token
41
    assert_raises(ActionController::InvalidAuthenticityToken) { delete :index }
42 43 44
  end
  
  def test_should_not_allow_xhr_post_without_token
45
    assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
46 47 48
  end
  
  def test_should_not_allow_xhr_put_without_token
49
    assert_raises(ActionController::InvalidAuthenticityToken) { xhr :put, :index }
50 51 52
  end
  
  def test_should_not_allow_xhr_delete_without_token
53
    assert_raises(ActionController::InvalidAuthenticityToken) { xhr :delete, :index }
54 55 56
  end
  
  def test_should_allow_post_with_token
57
    post :index, :authenticity_token => @token
58 59 60 61
    assert_response :success
  end
  
  def test_should_allow_put_with_token
62
    put :index, :authenticity_token => @token
63 64 65 66
    assert_response :success
  end
  
  def test_should_allow_delete_with_token
67
    delete :index, :authenticity_token => @token
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
    assert_response :success
  end
  
  def test_should_allow_post_with_xml
    post :index, :format => 'xml'
    assert_response :success
  end
  
  def test_should_allow_put_with_xml
    put :index, :format => 'xml'
    assert_response :success
  end
  
  def test_should_allow_delete_with_xml
    delete :index, :format => 'xml'
    assert_response :success
  end
end

87
module RequestForgeryProtectionActions
88 89 90 91
  def index
    render :inline => "<%= form_tag('/') {} %>"
  end
  
92 93 94 95
  def show_button
    render :inline => "<%= button_to('New', '/') {} %>"
  end
  
96 97 98 99 100 101 102
  def unsafe
    render :text => 'pwn'
  end
  
  def rescue_action(e) raise e end
end

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
class RequestForgeryProtectionController < ActionController::Base
  include RequestForgeryProtectionActions
  protect_from_forgery :only => :index, :secret => 'abc'
end

class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
  include RequestForgeryProtectionTests
  def setup
    @controller = RequestForgeryProtectionController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    class << @request.session
      def session_id() '123' end
    end
    @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
    ActionController::Base.request_forgery_protection_token = :authenticity_token
  end
end

# no token is given, assume the cookie store is used
class CsrfCookieMonsterController < ActionController::Base
  include RequestForgeryProtectionActions
  protect_from_forgery :only => :index
end

128 129 130 131 132 133 134
class FakeSessionDbMan
  def self.generate_digest(data)
    Digest::SHA1.hexdigest("secure")
  end
end

class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
135
  include RequestForgeryProtectionTests
136 137 138 139 140 141 142 143 144 145
  def setup
    @controller = CsrfCookieMonsterController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    # simulate a cookie session store
    @request.session.instance_variable_set(:@dbman, FakeSessionDbMan)
    class << @request.session
      attr_reader :dbman
    end
    @token = Digest::SHA1.hexdigest("secure")
146
    ActionController::Base.request_forgery_protection_token = :authenticity_token
147 148 149
  end
end