我的理解是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
作为值。
答案 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
标记。