rails – “警告:无法validationjsondevise请求的CSRF令牌真实性”

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

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

我可以把我的控制器skip_before_filter :verify_authenticity_token ,但我会失去CRSF保护(不build议:-))。

这个类似(仍然没有被接受)的答案暗示了

使用<%= form_authenticity_token %>检索标记

问题是如何? 我是否需要先打电话给我的任何页面来检索令牌,然后与Devise进行真正的身份validation? 或者它是我可以从我的服务器获得的一次性信息,然后一直使用(直到我手动在服务器上更改它)?

编辑

在Rails 4中,我现在使用@genkilabs在下面的注释中提出的build议:

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

其中,不是完全closures内置的安全性,而是在没有CSRF令牌的情况下击中服务器时可能会存在的任何会话。


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

这将closures已正确标记的jsonpost/ puts的CSRF检查。

例如,在iOS中将以下参数设置为您的NSURLRequest,其中“参数”是您的参数:


 [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]]]; 

您可以在成功login后使用自定义标题发送CSRF令牌。

例如,把这个放在你的会话中#create:

 response.headers['X-CSRF-Token'] = form_authenticity_token 

提供CSRF令牌的示例login响应头文件:

 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 

此令牌在您再次login之前是有效的,或者(如果您通过API支持,则注销)。 您的客户端可以从login响应头中提取并存储令牌。 然后,每个POST / PUT / DELETE请求必须使用在login时收到的值设置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= 

文档: form_authenticity_token

确实是最简单的方法。 不要打扰改变标题。

确保你有:

 <%= csrf_meta_tag %> 

在你的layouts/application.html.erb

只要做一个隐藏的input字段,如下所示:

 <input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>"/> 

或者,如果你想要一个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); } }); 

基本上,当你发布你的json数据只是添加一个有效的authenticity_token领域的post数据和警告应该消失…

我这样解决了这个错误:

 class ApplicationController < ActionController::Base protect_from_forgery skip_before_action :verify_authenticity_token, if: :json_request? protected def json_request? request.format.json? end end 

来源: http : //api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html

令人担忧的是,在Rails 3.2.3中,我们现在在production.log中获得CSRF警告,但是post并没有失败! 我希望它失败,因为它可以保护我免受攻击。 你可以在jQuery中添加csrf标记之前筛选btw:

http://jasoncodes.com/posts/rails-csrf-vulnerability

我已经使用了下面。 使用include? 所以如果内容types是application / json; charset = utf-8那么它仍然在工作。

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

这个答案比较好。

在任何XMLHttpRequest发送之前,您都可以保持CSRF-TOKENvalidation无需额外的工作(该标记被追加)。 没有JQuery,没有什么只是复制/粘贴和刷新。

只需添加此代码。

 (function() { var send = XMLHttpRequest.prototype.send, token = $('meta[name=csrf-token]').attr('content'); XMLHttpRequest.prototype.send = function(data) { this.setRequestHeader('X-CSRF-Token', token); return send.apply(this, arguments); }; }()); 

我有与以下版本的Rails相同的问题:
gem'rails',:git =>'git://github.com/rails/rails.git',:branch =>'3-2-stable'

我更新到3.2.2,现在一切正常。 🙂
gem轨“,”3.2.2“

今天晚上我遇到了同样的问题。 发生的原因是因为当你login时,最后一个csrf-token不再有效。 我做的是: $("meta[name=csrf-token]").attr('content', '<%= form_authenticity_token %>'); 在你的app / views / devise / sessions / create.js.rb中。

现在它有一个有效的csrf令牌:)我希望它可以帮助

也用于开发/testing模式。

 protect_from_forgery with: :exception unless %w(development test).include? Rails.env 

此警告显示,因为您正在使用:null_session ,在Rails 4.1中它默认工作,如果没有with:指定的选项。

 protect_from_forgery 

这不是一个错误。 它应该检查每个非GET请求。 https://github.com/rails/rails/issues/3041

Interesting Posts