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

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

class RequestForgeryProtectionController < ActionController::Base
8
  protect_from_forgery :only => :index, :secret => 'abc'
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

  def index
    render :inline => "<%= form_tag('/') {} %>"
  end
  
  def unsafe
    render :text => 'pwn'
  end
  
  def rescue_action(e) raise e end
end

class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
  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')
30
    ActionController::Base.request_forgery_protection_token = :authenticity_token
31 32 33 34 35 36 37 38
  end
  
  def teardown
    ActionController::Base.request_forgery_protection_token = nil
  end

  def test_should_render_form_with_token_tag
    get :index
39
    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  end

  # Replace this with your real tests.
  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
    assert_raises(ActionController::InvalidToken) { post :index }
  end
  
  def test_should_not_allow_put_without_token
    assert_raises(ActionController::InvalidToken) { put :index }
  end
  
  def test_should_not_allow_delete_without_token
    assert_raises(ActionController::InvalidToken) { delete :index }
  end
  
  def test_should_not_allow_xhr_post_without_token
    assert_raises(ActionController::InvalidToken) { xhr :post, :index }
  end
  
  def test_should_not_allow_xhr_put_without_token
    assert_raises(ActionController::InvalidToken) { xhr :put, :index }
  end
  
  def test_should_not_allow_xhr_delete_without_token
    assert_raises(ActionController::InvalidToken) { xhr :delete, :index }
  end
  
  def test_should_allow_post_with_token
78
    post :index, :authenticity_token => @token
79 80 81 82
    assert_response :success
  end
  
  def test_should_allow_put_with_token
83
    put :index, :authenticity_token => @token
84 85 86 87
    assert_response :success
  end
  
  def test_should_allow_delete_with_token
88
    delete :index, :authenticity_token => @token
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    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

# no token is given, assume the cookie store is used
class CsrfCookieMonsterController < ActionController::Base
110
  protect_from_forgery :only => :index
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

  def index
    render :inline => "<%= form_tag('/') {} %>"
  end
  
  def unsafe
    render :text => 'pwn'
  end
  
  def rescue_action(e) raise e end
end

class FakeSessionDbMan
  def self.generate_digest(data)
    Digest::SHA1.hexdigest("secure")
  end
end

class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
  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")
140
    ActionController::Base.request_forgery_protection_token = :authenticity_token
141 142 143 144 145 146 147 148
  end
  
  def teardown
    ActionController::Base.request_forgery_protection_token = nil
  end

  def test_should_render_form_with_token_tag
    get :index
149
    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
  end

  # Replace this with your real tests.
  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
    assert_raises(ActionController::InvalidToken) { post :index }
  end
  
  def test_should_not_allow_put_without_token
    assert_raises(ActionController::InvalidToken) { put :index }
  end
  
  def test_should_not_allow_delete_without_token
    assert_raises(ActionController::InvalidToken) { delete :index }
  end
  
  def test_should_not_allow_xhr_post_without_token
    assert_raises(ActionController::InvalidToken) { xhr :post, :index }
  end
  
  def test_should_not_allow_xhr_put_without_token
    assert_raises(ActionController::InvalidToken) { xhr :put, :index }
  end
  
  def test_should_not_allow_xhr_delete_without_token
    assert_raises(ActionController::InvalidToken) { xhr :delete, :index }
  end
  
  def test_should_allow_post_with_token
188
    post :index, :authenticity_token => @token
189 190 191 192
    assert_response :success
  end
  
  def test_should_allow_put_with_token
193
    put :index, :authenticity_token => @token
194 195 196 197
    assert_response :success
  end
  
  def test_should_allow_delete_with_token
198
    delete :index, :authenticity_token => @token
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    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