我正在使用AJAX将数据从视图发送到控制器,但出现此错误:
警告:无法验证CSRF令牌的真实性
我想我必须将此令牌与数据一起发送。
有人知道我该怎么做吗?
编辑:我的解决方案
我是通过将以下代码放入AJAX帖子中来完成此操作的:
headers: {
'X-Transaction': 'POST Example',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
我正在使用AJAX将数据从视图发送到控制器,但出现此错误:
警告:无法验证CSRF令牌的真实性
我想我必须将此令牌与数据一起发送。
有人知道我该怎么做吗?
编辑:我的解决方案
我是通过将以下代码放入AJAX帖子中来完成此操作的:
headers: {
'X-Transaction': 'POST Example',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
Answers:
你应该做这个:
确保<%= csrf_meta_tag %>
布局中有
添加beforeSend
到所有ajax请求中以设置标头,如下所示:
$.ajax({ url: 'YOUR URL HERE',
type: 'POST',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: 'someData=' + someData,
success: function(response) {
$('#someDiv').html(response);
}
});
要在所有请求中发送令牌,可以使用:
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
最好的方法实际上是<%= form_authenticity_token.to_s %>
直接在rails代码中打印出令牌。您无需使用javascript即可在dom中搜索csrf令牌,如其他帖子所述。只需添加headers选项,如下所示;
$.ajax({
type: 'post',
data: $(this).sortable('serialize'),
headers: {
'X-CSRF-Token': '<%= form_authenticity_token.to_s %>'
},
complete: function(request){},
url: "<%= sort_widget_images_path(@widget) %>"
})
如果我没记错的话,必须将以下代码添加到表单中,以解决此问题:
<%= token_tag(nil) %>
不要忘记参数。
<%= token_tag(nil) %>
。然后,您将获得自动生成的令牌。
确实是最简单的方法。不要为更改标题而烦恼。
确保您具有:
<%= csrf_meta_tag %> in your layouts/application.html.erb
只需执行一个隐藏的输入字段,如下所示:
<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);
}
});
从较旧的应用程序升级到Rails 3.1(包括csrf元标记)仍无法解决。在rubyonrails.org博客上,他们提供了一些升级技巧,特别是这行jquery,应该放在布局的开头部分:
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name='csrf-token']").attr("content");
xhr.setRequestHeader("X-CSRF-Token", token);
});
摘自此博客文章:http : //weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails。
就我而言,会话是在每个ajax请求后重置的。添加上面的代码解决了该问题。
<%= csrf_meta_tag %>
布局中有beforeSend
以在ajax请求中包含csrf令牌以设置标头。仅对于post
请求是必需的。可以使用读取csrf令牌的代码rails/jquery-ujs
,因此恕我直言,使用它最简单,如下所示:
$.ajax({
url: url,
method: 'post',
beforeSend: $.rails.CSRFProtection,
data: {
// ...
}
})
headers: { 'X-CSRF-Token': Rails.csrfToken() }
我只是想将其链接到这里,因为本文包含了您正在寻找的大多数答案,而且也很有趣
此处票数最高的答案是正确的,但是如果您执行跨域请求,则该答案将不起作用,因为除非您明确告诉jQuery传递会话cookie,否则该会话将不可用。这样做的方法如下:
$.ajax({
url: url,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
},
xhrFields: {
withCredentials: true
}
});
您可以像下面这样全局地编写它。
普通JS:
$(function(){
$('#loader').hide()
$(document).ajaxStart(function() {
$('#loader').show();
})
$(document).ajaxError(function() {
alert("Something went wrong...")
$('#loader').hide();
})
$(document).ajaxStop(function() {
$('#loader').hide();
});
$.ajaxSetup({
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}
});
});
咖啡脚本:
$('#loader').hide()
$(document).ajaxStart ->
$('#loader').show()
$(document).ajaxError ->
alert("Something went wrong...")
$('#loader').hide()
$(document).ajaxStop ->
$('#loader').hide()
$.ajaxSetup {
beforeSend: (xhr) ->
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
}
哎呀..
我错过了我的application.js中的以下行
//= require jquery_ujs
我更换了它,它的工作..
=======更新=========
5年后,我返回了Same错误,现在有了全新的Rails 5.1.6,并且再次找到了这篇文章。就像生活圈。
现在的问题是: Rails 5.1默认删除了对jquery和jquery_ujs的支持,并添加了
//= require rails-ujs in application.js
它执行以下操作:
但是,为什么不为ajax请求包括csrf令牌呢?如果有人对此有详细了解,请评论我。我很感激。
无论如何,我在自定义js文件中添加了以下内容以使其正常运行(感谢其他答案,以帮助我达到此代码):
$( document ).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-Token': Rails.csrfToken()
}
});
----
----
});
jquery_ujs
。那是诀窍。
如果您不使用jQuery并使用类似fetch API之类的请求,则可以使用以下命令获取csrf-token
:
document.querySelector('meta[name="csrf-token"]').getAttribute('content')
fetch('/users', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')},
credentials: 'same-origin',
body: JSON.stringify( { id: 1, name: 'some user' } )
})
.then(function(data) {
console.log('request succeeded with JSON response', data)
}).catch(function(error) {
console.log('request failed', error)
})
使用jquery.csrf(https://github.com/swordray/jquery.csrf)。
Rails 5.1或更高版本
$ yarn add jquery.csrf
//= require jquery.csrf
Rails 5.0或更低版本
source 'https://rails-assets.org' do
gem 'rails-assets-jquery.csrf'
end
//= require jquery.csrf
源代码
(function($) {
$(document).ajaxSend(function(e, xhr, options) {
var token = $('meta[name="csrf-token"]').attr('content');
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
});
})(jQuery);
//= require jquery.csrf
行不通,对吧?相反,我在其中使用了pack js文件import 'jquery.csrf'
。注意:你不必须与你的意见包装标签包括这个。
对于确实需要非jQuery答案的用户,您可以简单地添加以下内容:
xmlhttp.setRequestHeader('X-CSRF-Token',$('meta [name =“ csrf-token”]')。attr('content'));
在这里可以举一个非常简单的例子:
xmlhttp.open(“ POST”,“ example.html”,true); xmlhttp.setRequestHeader('X-CSRF-Token',$('meta [name =“ csrf-token”]')。attr('content')); xmlhttp.send();
我为这个问题苦苦挣扎了好几天。任何GET调用均正常工作,但是所有PUT都会生成“无法验证CSRF令牌真实性”错误。在向nginx添加SSL证书之前,我的网站运行良好。
我终于在我的nginx设置中偶然发现了这条缺失的线:
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto https; # Needed to avoid 'WARNING: Can't verify CSRF token authenticity'
proxy_pass http://puma;
}
添加缺少的行“ proxy_set_header X-Forwarded-Proto https;”之后,我所有的CSRF令牌错误都退出了。
希望这可以帮助其他也在墙上撞头的人。哈哈
如果有人需要与Uploadify和Rails 3.2相关的帮助(当我在这篇文章上搜索时像我一样),此示例应用程序可能会有所帮助:https : //github.com/n0ne/Uploadify-Carrierwave-Rails-3.2.3/blob/master /app/views/pictures/index.html.erb
还要检查此应用程序中的控制器解决方案
我正在使用Rails 4.2.4,无法弄清楚为什么我得到了:
Can't verify CSRF token authenticity
我在布局中:
<%= csrf_meta_tags %>
在控制器中:
protect_from_forgery with: :exception
调用tcpdump -A -s 999 -i lo port 3000
显示正在设置的标题(尽管不需要使用设置标题ajaxSetup
-已经完成):
X-CSRF-Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
DNT: 1
Content-Length: 125
authenticity_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
最后,它失败了,因为我关闭了Cookie。如果未启用Cookie,CSRF将无法工作,因此,如果您看到此错误,则这是另一个可能的原因。