覆盖控制器中的protect_from_forgery策略

时间:2014-05-15 08:31:22

标签: ruby-on-rails ruby override csrf

我想使用两种不同的protect_from_forgery策略构建一个rails应用程序:一个用于Web应用程序,另一个用于API。

在我的应用程序控制器中,我有这行代码:protect_from_forgery with: :exception为了防止CSRF攻击,它运行正常。

在我的API命名空间中,我创建了一个从我的应用程序控制器继承的api_controller,它是API命名空间中所有其他控制器的父类,我更改了上面的代码:protect_from_forgery with: :null_session。< / p>

可悲的是,我在尝试发出POST请求时遇到错误:“无法验证CSRF令牌的真实性”。

我不想跳过API控制器中的verify_authenticity_token方法,我只想在我的应用程序中有两个不同的策略,那么如何覆盖应用程序控制器中定义的protect_from_forgery策略呢?

编辑:好的,所以我最终做了我最初不想做的事情:改变我的api_controller的继承:它现在继承自ActionController :: Base,而不再是我的应用控制器。它现在确实有效,但是:

  1. 它没有回答我的问题,即覆盖protect_from_forgery策略。
  2. 它不是DRY,因为我必须复制/覆盖之前在我的application_controller中的内容。
  3. 因此,如果有人有真正的方法来覆盖这种方法,我会很感激。

3 个答案:

答案 0 :(得分:11)

如果您将protect_from_forgery with: :exception留在应用程序控制器中,然后将以下内容放在API控制器中,该怎么办?

skip_before_action :protect_from_forgery
protect_from_forgery with: :null_session

这样,您仍然可以获得Web应用程序中所有控制器的标准CSRF攻击保护,但您也可以获得API方法的空会话行为。

答案 1 :(得分:3)

我正在运行一个类似结构的应用程序 - Web App + API。我解决了这样的CSRF问题:

  • 仅针对非API请求应用protect_from_forgery
  • 我的API端点是api.example.com,因此我使用子域约束来区分API和Web应用程序请求

代码:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception, if: :isWebRequest?

  def isWebRequest?
    request.subdomains[-1] != 'api'
  end

end

答案 2 :(得分:0)

迟到聚会,但是可以这样做:

class YourCustomStrategy
  def initialize(controller)
  end

  def handle_request
  end
end

在您的ApplicationController中或您想要的位置:

class ApplicationController < ActionController::Base
 protect_from_forgery with: YourCustomStrategy
end