如果我不包含真实性令牌,那么不应该使用:: exception异常引发错误吗?

时间:2017-06-13 23:36:47

标签: ruby-on-rails ruby

我的理解是protect_from_forgery with: :exception这是Rails中的默认设置,如果提交了表单并且他们没有authenticity_token输入,则会导致错误。

然而,似乎情况不再如此。这是一个Rails 5应用程序,我过去主要做了Rails 4,所以我想知道是否有变化。

在application_controller.rb中我有protect_from_forgery with: :exception

我的表格是这样的(使用苗条)

form#spreadsheet-form{
  action='/submit_spreadsheet'
}
  textarea.spreadsheet-input{
    name='instructions'
    style="width: 200px; height: 200px"
  }
  br
  input.spreadsheet-submit{
    type="submit"
    value="submit"
  }

我眼中的主要问题是为什么这不会引起错误。在过去,我必须包含一个隐藏的输入form_authencicity_token作为值。

2 个答案:

答案 0 :(得分:1)

我认为这与 Rails 5 更改了protect_from_forgery执行顺序有关。从blog

开始

<强>什么

如果我们在 Rails 4.x 中生成全新的Rails应用程序,则application_controller将如下所示。

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

在代码中查看它看起来不像protect_from_forgery before_action,但实际上就是这样。由于protect_from_forgery是before_action调用,因此它应遵循执行其他before_action的顺序。但是这一点很特殊,因为protect_from_forgery首先在before_action系列中执行,无论在哪里提到protect_from_forgery。我们来看一个例子。

class ApplicationController < ActionController::Base
  before_action :load_user
  protect_from_forgery with: :exception
end

在上述情况下,即使在load_user之后进行protect_from_forgery调用,也会首先发生保护执行。我们无能为力。我们无法通过任何选项来阻止Rails这样做。

Rails 5 通过引入名为prepend 的布尔选项来更改此行为。此选项的默认值为false。这意味着,现在protect_from_forgery按呼叫顺序执行。当然,这可以通过传递prepend: true来覆盖,如下所示,现在保护调用将首先发生,就像 Rails 4.x 一样。

class ApplicationController < ActionController::Base
  before_action :load_user
  protect_from_forgery with: :exception, prepend: true
end

<强>为什么

强制protect_from_forgery成为要执行的过滤器链中的第一个过滤器没有任何实际优势。另一方面,有些情况下其他before_action的输出应决定protect_from_forgery的执行。我们来看一个例子。

class ApplicationController < ActionController::Base
  before_action :authenticate
  protect_from_forgery unless: -> { @authenticated_by.oauth? }

  private
    def authenticate
      if oauth_request?
        # authenticate with oauth
        @authenticated_by = 'oauth'.inquiry
      else
        # authenticate with cookies
        @authenticated_by = 'cookie'.inquiry
      end
    end
end

上面的代码在 Rails 4.x 中会失败,因为protect_from_forgery虽然在:authenticate之后调用,但实际上会在它之前执行。因此,我们无法正确设置@authenticated_by

Rails 5 中,protect_from_forgery:authenticate之后执行,如果身份验证是oauth则会被跳过

答案 1 :(得分:0)

您检查表单时是否存在真品标记?在您的申请中插入protect_from_forgery的哪一点?

Rails 4 =&gt; 5更改了默认行为,无论它在链中的哪个位置都被插入,与先前调用它的位置相反。如果您希望在执行任何其他操作之前调用它,请尝试使用prepend: true标记。