request_forgery_protection_test.rb 5.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
require File.dirname(__FILE__) + '/../abstract_unit'

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

class RequestForgeryProtectionController < ActionController::Base
  verify_token :only => :index, :secret => 'abc'

  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')
    ActionController::Base.request_forgery_protection_token = :_token
  end
  
  def teardown
    ActionController::Base.request_forgery_protection_token = nil
  end

  def test_should_render_form_with_token_tag
    get :index
    assert_select 'form>div>input[name=?][value=?]', '_token', @token
  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
    post :index, :_token => @token
    assert_response :success
  end
  
  def test_should_allow_put_with_token
    put :index, :_token => @token
    assert_response :success
  end
  
  def test_should_allow_delete_with_token
    delete :index, :_token => @token
    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
  verify_token :only => :index

  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")
    ActionController::Base.request_forgery_protection_token = :_token
  end
  
  def teardown
    ActionController::Base.request_forgery_protection_token = nil
  end

  def test_should_render_form_with_token_tag
    get :index
    assert_select 'form>div>input[name=?][value=?]', '_token', @token
  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
    post :index, :_token => @token
    assert_response :success
  end
  
  def test_should_allow_put_with_token
    put :index, :_token => @token
    assert_response :success
  end
  
  def test_should_allow_delete_with_token
    delete :index, :_token => @token
    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