Rails 4真实性令牌


198

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

在编写一个响应json的控制器时(使用respond_toclass方法),当我尝试使用创建记录时,我得到了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应用程序中创建新记录,而没有进行任何更改,而且我遇到了相同的问题,所以我想这不是我做的。

Answers:


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

20
您可以一起删除:with选项,:null_session是默认设置:api.rubyonrails.org/classes/ActionController/…–
Casey

6
有没有一种方法可以将异常用于非JSON调用,并将空会话用于JSON调用(又称API调用)?
James McMahon 2014年

@JamesMcMahon您可能可以编写自己before_action的格式检查格式以及请求是否经过验证的文件。我不知道设置条件的任何内置方式。
alexcoco 2014年

1
在rails 4.1.6中,我还必须skip_before_action :verify_authenticity_token在API的应用程序控制器上进行指定,以使其正常工作。
Waseem

1
您无需:verify_authenticy_token在Rails 4.2中禁用更多功能。它默认为:null_session,顾名思义,它只是在不进行会话的情况下为您提供请求。您可以改为通过API密钥验证请求。
罗巴蒂

72

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

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

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


9
如果您要创建表单,这是一个很好的建议,但问题是要使用JSON进行API调用。
詹姆斯·麦克马洪

1
不过,谢谢您,这回答了我在使用把手时手写代码的问题!
David Routen

70

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

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

12
并不是真的适用于api调用
courtsimas 2014年

2
就我而言,我正在使用Rails4。我可以通过单击提交按钮来提交表单。但是,如果我通过JS代码提交表单,则会发生此错误。这个答案为我解决了问题。
Chris.Zou 2014年

2
对于基于Rails 4.0.8的应用程序,足以编写=token_tag nil或(在.erb中)<%= token_tag nil %>
jmarceli 2014年

1
您似乎通过将令牌设置为nil来禁用身份验证?
卡洛斯(Carlos)

这样安全吗?
Angel Garcia

33

只要您不专门实现API,我一般不建议关闭CSRF保护。

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

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

class FooController < ApplicationController
  protect_from_forgery except: :index

这在Rails 4中为我完成了-尝试删除后抛出错误。^^
zero_cool 2014年

9

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

      skip_before_filter :verify_authenticity_token, if: :json_request?

未定义的方法“ json_request?” 对于#<SettingsController:0x000000030a54a8>,知道吗?
Deano

您必须在那里定义一个方法,例如:def json_request?request.format.json?结束
贾伊·库玛·拉杰普特

7

你试过了吗?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }



2

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

像这样

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

这是用于不同版本的导轨的一些行。

导轨3

skip_before_filter:verify_authenticity_token

Rails 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

1

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

jquery-ujs可以为您管理令牌

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

//= require jquery_ujs

这就是您所需的一切-您的ajax调用现在应该可以了

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



0

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

<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表单帮助程序,而不是损害安全性等。


1
感谢您的回答,尽管这不能回答原始问题。该问题询问有关响应JSON请求的问题,但您正在为从头开始的HTML表单提供解决方案。发出JSON请求(使用API​​)时,您未提交HTML表单,并且可能无法轻松访问真实性令牌。
alexcoco 2014年

除非请求的内容实际上是JSON,否则您需要将其设置为application/json
alexcoco 2014年

我了解答案并不完全是您想要的。但是提出相关答案的目的是帮助用户寻找类似的“真实性问题”。
amjad 2014年

抱歉,我错误地删除了“您可以使用上述解决方案设置Content-Type:application / x-www-form-urlencoded”。
amjad 2014年

0

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

export RAILS_ENV=something_non_test

我忘记取消设置此变量,因此我开始遇到ActionController::InvalidAuthenticityToken异常。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.