2013-04-28 64 views
187

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

在写一个控制器,响应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应用程序,我遇到了同样的问题,所以我想这不是我做的事。

回答

270

我想我只是想通了。我改变了(新)的默认

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 

这将调用the following

def handle_unverified_request 
    raise ActionController::InvalidAuthenticityToken 
end 
+20

你可以一起删除:with选项:null_session是默认值:http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html – Casey 2013-08-20 20:29:52

+5

有没有办法使用异常的非JSON JSON调用(aka API调用)的调用和空会话? – 2014-01-09 14:38:05

+0

@JamesMcMahon您可以编写自己的'before_action'来检查格式和请求是否被验证。我不知道任何建立条件的方式。 – alexcoco 2014-01-09 15:11:35

31

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

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

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

class FooController < ApplicationController 
    protect_from_forgery except: :index 
+0

这对我来说是在Rails 4中做的 - 试图删除后抛出错误。 ^^ – 2014-09-26 13:54:28

67

而是关闭CSRF保护的,最好是下面的代码行添加到窗体

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

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

+9

如果您正在制作表单,这是一个很好的建议,但问题在于使用JSON进行API调用。 – 2014-01-09 14:34:32

+1

尽管谢谢,这回答了我在使用手柄时手写代码的问题! – DerProgrammer 2014-07-02 21:48:12

65

将以下行添加到表单中工作对我来说:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %> 
+12

并不适用于api调用 – courtsimas 2014-04-15 16:03:25

+2

比上面的代码更简洁。谢谢! – DerProgrammer 2014-07-02 21:48:55

+2

就我而言,我使用的是Rails4。我可以通过点击提交按钮来提交表格。但是,如果我通过JS代码提交表单,则会发生此错误。这个答案解决了我的问题。 – 2014-07-25 10:37:22

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> 

因此,解决问题的办法是要么添加authenticity_token场或使用轨道形成的助手而不是损害安全性等

+1

谢谢你的回答,虽然这不回答原来的问题。这个问题是关于响应JSON请求的问题,但您提供的是一种从头开始的HTML表单的解决方案。在提出JSON请求(认为API)时,您并未提交HTML表单,并且您可能无法轻松访问真实性标记。 – alexcoco 2014-07-06 13:20:16

+0

,除非请求的内容实际上是JSON,在这种情况下,您希望将其设置为“application/json”。 – alexcoco 2014-07-06 13:35:31

+0

我明白答案不完全是你要找的。但相关答案的目的是帮助用户寻找类似的“真实性问题”。 – amjad 2014-07-06 13:39:50

8

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

 skip_before_filter :verify_authenticity_token, if: :json_request? 
+0

未定义的方法'json_request?'为#,任何想法? – Deano 2016-03-23 12:30:39

+0

你必须在那里定义一个方法: def json_request? request.format.json? 结束 – 2016-12-28 06:01:55

6

您试过吗?

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

导轨4

skip_before_action:verify_authenticity_token


你应该打算禁用该安全功能对所有控制器程序,你可以protect_from_forgery的值更改为:您application_controller.rb文件null_session

像这样,

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

如果你正在使用jQuery与轨,警惕允许进入方法未经核实真实性令牌。

jQuery的UJS可以管理令牌你

你应该有它已经作为jQuery的轨道宝石的一部分,但你可能需要把它列入的application.js

//= require jquery_ujs 

这就是你所需要的 - 你的Ajax调用现在应该工作

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

1

添加authenticity_token: true到窗体标记

0

我所有的测试都正常工作。但由于某些原因,我已经把我的环境变量,以非测试:

export RAILS_ENV=something_non_test 

我忘了取消设置这个变量,因为这些我开始ActionController::InvalidAuthenticityToken例外。

未设置$RAILS_ENV后,我的测试重新开始工作。