200

当我遇到一些真实性令牌问题时,我正在开发一个新的 Rails 4 应用程序(在 Ruby 2.0.0-p0 上)。

在编写响应 json 的控制器(使用respond_to类方法)时,我create开始ActionController::InvalidAuthenticityToken尝试使用curl.

我确定我设置-H "Content-Type: application/json"并设置了数据,-d "<my data here>"但仍然没有运气。

我尝试使用 Rails 3.2(在 Ruby 1.9.3 上)编写相同的控制器,但我没有遇到任何真实性令牌问题。我四处搜索,发现 Rails 4 中的真实性令牌发生了一些变化。据我了解,它们不再自动插入表单中了吗?我想这会以某种方式影响非 HTML 内容类型。

有没有办法绕过这个问题,而不必请求 HTML 表单,获取真实性令牌,然后使用该令牌发出另一个请求?还是我完全错过了一些完全明显的东西?

编辑:我刚刚尝试使用脚手架在一个新的 Rails 4 应用程序中创建一个新记录,而不做任何更改,我遇到了同样的问题,所以我想这不是我所做的。

4

13 回答 13

277

我想我刚刚想通了。我更改了(新)默认值

protect_from_forgery with: :exception

protect_from_forgery with: :null_session

根据中的评论ApplicationController

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

您可以通过查看 的源代码request_forgery_protecton.rb,或者更具体地说,查看以下几行代码来查看差异:

Rails 3.2中:

# This is the method that defines the application behavior when a request is found to be unverified.
# By default, \Rails resets the session when it finds an unverified request.
def handle_unverified_request
  reset_session
end

Rails 4中:

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

这将调用以下内容

def handle_unverified_request
  raise ActionController::InvalidAuthenticityToken
end
于 2013-04-28T15:35:21.310 回答
73

与其关闭csrf保护,不如在表单中加入下面这行代码

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

如果您使用 form_for 或 form_tag 生成表单,那么它会自动在表单中添加上述代码行

于 2013-09-29T15:05:30.200 回答
71

将以下行添加到表单中对我有用:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
于 2013-10-25T08:36:33.843 回答
33

只要您不专门实现 API,我认为通常关闭 CSRF 保护并不是一件好事。

在查看ActionController的 Rails 4 API 文档时,我发现您可以在每个控制器或每个方法库上关闭伪造保护。

例如,为您可以使用的方法关闭 CSRF 保护

class FooController < ApplicationController
  protect_from_forgery except: :index
于 2013-08-07T05:44:37.870 回答
9

遇到了同样的问题。通过添加到我的控制器来修复它:

      skip_before_filter :verify_authenticity_token, if: :json_request?
于 2014-12-19T19:59:48.540 回答
7

你试过了吗?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
于 2015-04-01T13:01:47.810 回答
5

这个官方文档 - 讨论如何正确关闭 api 的伪造保护 http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html

于 2015-11-19T22:28:35.213 回答
3

这是 Rails 中的一个安全特性。在表单中添加这行代码:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

文档可以在这里找到:http: //api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html

于 2016-02-03T05:34:33.720 回答
2

这些功能是出于安全和防伪目的而添加的。
但是,为了回答您的问题,这里有一些输入。您可以在控制器名称之后添加这些行。

像这样,

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

以下是不同版本的导轨的一些行。

导轨 3

skip_before_filter :verify_authenticity_token

导轨 4

skip_before_action :verify_authenticity_token


如果您打算为所有控制器例程禁用此安全功能,您可以在 application_controller.rb 文件中将protect_from_forgery 的值更改: null_session

像这样,

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
end
于 2016-12-19T10:07:35.357 回答
1

添加authenticity_token: true到表单标签

于 2017-08-16T14:56:01.693 回答
1

如果您将 jQuery 与 rails 一起使用,请注意在未验证真实性令牌的情况下允许进入方法。

jquery-ujs 可以为你管理令牌

您应该已经将它作为 jquery-rails gem 的一部分,但您可能需要将它包含在 application.js 中

//= require jquery_ujs

这就是你所需要的——你的 ajax 调用现在应该可以工作了

更多信息参见: https ://github.com/rails/jquery-ujs

于 2017-06-05T15:19:11.043 回答
0

当您定义自己的 html 表单时,您必须包含身份验证令牌字符串,出于安全原因,应将其发送到控制器。如果您使用 Rails 表单助手生成真实性令牌,则会将其添加到表单中,如下所示。

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
  </div>
    ...
</form>

因此问题的解决方案是添加authentity_token 字段或使用rails 表单助手,而不是损害安全性等。

于 2014-07-06T12:10:39.357 回答
0

我所有的测试都运行良好。但由于某种原因,我将环境变量设置为非测试:

export RAILS_ENV=something_non_test

我忘了取消设置这个变量,因为我开始遇到ActionController::InvalidAuthenticityToken异常。

取消设置后$RAILS_ENV,我的测试再次开始工作。

于 2017-11-21T08:59:12.643 回答