rails - 对于json设计请求,"警告:无法验证CSRF令牌真实性"

81 csrf devise ruby-on-rails-3 ruby-on-rails-3.1

如何检索CSRF令牌以传递JSON请求?

我知道出于安全原因,Rails正在检查所有请求类型(包括JSON/XML)上的CSRF令牌.

我可以放入我的控制器skip_before_filter :verify_authenticity_token,但我会失去CRSF保护(不建议:-)).

这个类似的(仍未被接受的)答案暗示

检索令牌 <%= form_authenticity_token %>

问题是如何?我是否需要先对我的任何页面进行调用以检索令牌,然后使用Devise进行真正的身份验证?或者它是一个一次性的信息,我可以从我的服务器获得然后一致地使用(直到我在服务器本身手动更改它)?

Rya*_*ews 127

编辑:

在Rails 4中,我现在使用@genkilabs在下面的评论中建议的内容:

protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }

这不是完全关闭内置安全性,而是在没有CSRF令牌的情况下杀死服务器时可能存在的任何会话.


skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }

这将关闭已正确标记为json post/puts的CSRF检查.

例如,在iOS中将以下内容设置为NSURLRequest,其中"parameters"是您的参数:


[request setHTTPMethod:@"POST"];

[request setValue:@"application/json" 
       forHTTPHeaderField:@"content-type"];

[request setValue:@"application/json" 
       forHTTPHeaderField:@"accept"];

[request setHTTPBody:[NSData dataWithBytes:[parameters UTF8String] 
                                            length:[parameters length]]];
Run Code Online (Sandbox Code Playgroud)

  • 您受到攻击,这就是为什么他们建议您在关闭过滤器时有其他安全措施.通常,对于API请求,请求者将发送API密钥以及发布数据,然后在执行所需方法之前验证. (21认同)
  • 在rails 4中,您可以执行以下操作:```protect_from_forgery with :: null_session,:if => Proc.new {| c | c.request.format =='application/json'}``` (18认同)
  • 这样做,如果攻击者将格式标记为"json",则会受到攻击.这就是Rails定义发出警告的原因.我希望让我的json能够正确传递令牌,否则在日志中发出警告就可以了. (3认同)
  • @genkilabs我喜欢这个,为rails 4用户添加回答,谢谢=] (2认同)

小智 18

成功登录后,您可以使用自定义标头发送CSRF令牌.

例如,将它放在你的会话中#create:

response.headers['X-CSRF-Token'] = form_authenticity_token
Run Code Online (Sandbox Code Playgroud)

提供CSRF令牌的示例登录响应头:

HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Connection: Keep-Alive
Content-Length: 35
Content-Type: application/json; charset=utf-8
Date: Mon, 22 Oct 2012 11:39:04 GMT
Etag: "9d719d3b9aabd413c3603e04e8a3933d"
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
Set-Cookie: [cut for readability] 
X-Csrf-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
X-Request-Id: 178746992d7aca928c876818fcdd4c96
X-Runtime: 0.169792
X-Ua-Compatible: IE=Edge
Run Code Online (Sandbox Code Playgroud)

此令牌在您再次登录之前有效,或者(如果您通过API支持,则退出).您的客户端可以从登录响应标头中提取和存储令牌.然后,每个POST/PUT/DELETE请求必须使用在登录时接收的值设置X-CSRF-Token标头.

使用CSRF令牌的POST标头示例:

POST /api/report HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Type: application/json; charset=utf-8
Cookie: [cut for readability]
Host: localhost:3000
User-Agent: HTTPie/0.3.0
X-CSRF-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
Run Code Online (Sandbox Code Playgroud)

文档:form_authenticity_token


小智 16

确实最简单的方法.不要在改变标题时烦恼.

确保你有:

<%= csrf_meta_tag %>
Run Code Online (Sandbox Code Playgroud)

在你的 layouts/application.html.erb

只做一个隐藏的输入字段,如下所示:

<input name="authenticity_token" 
       type="hidden" 
       value="<%= form_authenticity_token %>"/>
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个jquery ajax帖子:

$.ajax({     
    type: 'POST',
    url: "<%= someregistration_path %>",
    data: { "firstname": "text_data_1", "last_name": "text_data2", "authenticity_token": "<%= form_authenticity_token %>" },                                                                                  
    error: function( xhr ){ 
      alert("ERROR ON SUBMIT");
    },
    success: function( data ){ 
      //data response can contain what we want here...
      console.log("SUCCESS, data="+data);
    }
});
Run Code Online (Sandbox Code Playgroud)

基本上当你发布你的json数据时,只需在数据中添加一个有效的authenticity_token字段,post警告就会消失......