【问题标题】:Override action_controller.allow_forgery_protection for specific integration test为特定的集成测试覆盖 action_controller.allow_forgery_protection
【发布时间】:2011-05-06 23:11:06
【问题描述】:

我有一个 rails3 应用程序,它在我的基本应用程序控制器中使用 protect_from_forgery。我正在使用 ActionDispatch::IntegrationTest 并希望确保在某些集成测试期间存在真实性令牌。

我不希望执行帖子的每个功能测试都必须传递authenticity_token,所以我的test.rb 文件指定:

  config.action_controller.allow_forgery_protection    = false

正如 rails 文档所建议的那样。

但是,对于集成测试,我很想确保我的表单正确发送了真实性令牌。如果不更改 config/environments/test.rb 中的全局设置,我找不到任何方法来做到这一点

如果我所有的表单都是用form_for 生成的,我会相信 rails 会处理这个问题,但是我使用 ExtJS 并且有许多需要手动指定的 ExtJS 表单,所以我真的应该测试一下管道一切正常。

【问题讨论】:

    标签: ruby-on-rails security ruby-on-rails-3 testing integration-testing


    【解决方案1】:

    临时为区块启用伪造保护的辅助方法:

    def with_forgery_protection
      orig = ActionController::Base.allow_forgery_protection
      begin
        ActionController::Base.allow_forgery_protection = true
        yield if block_given?
      ensure
        ActionController::Base.allow_forgery_protection = orig
      end
    end
    
    with_forgery_protection do
      # code in here will require csrf token
    end
    

    【讨论】:

      【解决方案2】:

      您可以简单地更改集成测试设置中的值:

      require 'test_helper'
      
      class MyCrunchyIntegrationTest < ActionController::IntegrationTest
        fixtures :all
      
        def setup
          ActionController::Base.allow_forgery_protection = true
        end
      
        def teardown
          ActionController::Base.allow_forgery_protection = false
        end
      
        test "how awesome my application is" do
          # ...
        end
      end
      

      【讨论】:

      • 但这不会为下一次测试重置它! IMO gmcnaughton 的答案更好。
      • 是的。编辑以重置 teardown 方法中的值。不过,使用@gmcnaughton 建议的块可能会更好地进行更精细的控制。
      【解决方案3】:

      这是@gmcnaughton 解决方案的 RSpec 版本。

      这在spec_helper.rb:

      RSpec.configure do |config|
        config.around(:each, :with_csrf_protection) do |example|
          orig = ActionController::Base.allow_forgery_protection
      
          begin
            ActionController::Base.allow_forgery_protection = true
            example.run
          ensure
            ActionController::Base.allow_forgery_protection = orig
          end
        end
      end
      

      然后你编写如下测试:

      it "foo", with_csrf_protection: true do
        # …
      end
      

      或者,取决于您的 RSpec 设置:

      it "foo", :with_csrf_protection do
        # …
      end
      

      【讨论】:

      • 这可以被 lib/rspec/rails/example/controller_example_group.rb:188 中包含的 around 过滤器覆盖,因此更适合请求规范而不是控制器规范
      猜你喜欢
      • 1970-01-01
      • 2016-06-15
      • 2013-10-14
      • 2017-11-22
      • 2011-12-26
      • 1970-01-01
      • 2018-10-18
      • 2020-01-08
      • 2016-01-16
      相关资源
      最近更新 更多