Rails 4 中的真实性令牌

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

在编写响应json的控制器(使用respond_to类方法)时,我得到了create动作,当我试图使用curl创建记录时,我开始得到ActionController::InvalidAuthenticityToken异常。

我确保我设置了-H "Content-Type: application/json",我设置了-d ""的数据,但仍然没有运气。

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

有没有什么方法可以解决这个问题,而不需要请求HTML表单,获取真实性令牌,然后使用该令牌发出另一个请求?还是我完全忽略了一些非常明显的东西?

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

130456 次浏览

我想我明白了。我更改了(新的)默认值

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

我认为只要不专门实现某个API,一般关闭CSRF保护是不好的。

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

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

class FooController < ApplicationController
protect_from_forgery except: :index

与其关闭csrf保护,不如将以下代码行添加到表单中

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

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

在表单中添加以下代码对我来说很有效:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

当你定义你自己的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>

因此,解决问题的方法是添加authenticity_token字段或使用rails表单助手,而不是牺牲安全性等。

遇到了同样的问题。修正了添加到我的控制器:

      skip_before_filter :verify_authenticity_token, if: :json_request?

你试过吗?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
这个官方文档讨论了如何正确地关闭api的伪造保护 http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html < / p >

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

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

文件可以在这里找到: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html < / p >

增加这些特性是出于安全和防伪造的目的 不过,为了回答你的问题,这里有一些建议。 你可以在你的控制器名称后面添加这些行

像这样,

class NameController < ApplicationController
skip_before_action :verify_authenticity_token

下面是一些用于不同版本的rails的行。

Rails 3

skip_before_filter: verify_authenticity_token

Rails 4:

skip_before_action: verify_authenticity_token

< p >
如果你打算为所有控制器例程禁用此安全特性,你可以在你的应用程序控制器上将protect_from_forgery的值更改为: null_session。rb文件。< / p >

像这样,

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

如果您正在使用jQuery和rails一起使用,请注意不要在没有验证真实性令牌的情况下允许进入方法。

Jquery-ujs可以帮你管理这些令牌

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

//= require jquery_ujs

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

欲了解更多信息,请参见: https://github.com/rails/jquery-ujs < / p >

authenticity_token: true添加到form标签中

我所有的测试都很正常。但出于某种原因,我将环境变量设置为非测试:

export RAILS_ENV=something_non_test

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

在取消设置$RAILS_ENV之后,我的测试又开始工作了。