提问人:kbaccouche 提问时间:8/26/2011 最后编辑:RyanSkbaccouche 更新时间:10/2/2023 访问量:175397
警告:无法验证 CSRF 令牌真实性轨道
WARNING: Can't verify CSRF token authenticity rails
问:
我正在使用 AJAX 将数据从视图发送到控制器,我收到此错误:
警告:无法验证 CSRF 令牌的真实性
我想我必须发送这个带有数据的令牌。
有谁知道我该怎么做?
编辑:我的解决方案
我通过将以下代码放在 AJAX 帖子中来做到这一点:
headers: {
'X-Transaction': 'POST Example',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
答:
如果我没记错的话,您必须将以下代码添加到表单中,以解决此问题:
<%= token_tag(nil) %>
不要忘记参数。
评论
<%= token_tag(nil) %>
您应该这样做:
确保你的布局中有
<%= csrf_meta_tag %>
添加到所有 ajax 请求中以设置标头,如下所示:
beforeSend
$.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')
}
});
评论
我只是想我会在这里链接这个,因为这篇文章包含您正在寻找的大部分答案,而且也非常有趣
最好的方法实际上是直接在你的 rails 代码中打印出令牌。您不需要像其他帖子提到的那样使用 javascript 在 dom 中搜索 csrf 令牌。只需添加标题选项,如下所示;<%= form_authenticity_token.to_s %>
$.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) %>"
})
评论
从较旧的应用程序升级到 rails 3.1,包括 csrf meta 标签仍然无法解决它。在 rubyonrails.org 博客上,他们提供了一些升级技巧,特别是这一行jquery,它应该放在布局的head部分:
$(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请求时都会被重置。添加上面的代码解决了这个问题。
如果您将 javascript 与 jQuery 一起使用以在表单中生成令牌,则有效:
<input name="authenticity_token"
type="hidden"
value="<%= $('meta[name=csrf-token]').attr('content') %>" />
显然,你需要在你的 Ruby 布局中加入它。<%= csrf_meta_tag %>
如果有人需要与 Uploadify 和 Rails 3.2 相关的帮助(就像我在谷歌上搜索这篇文章时一样),这个示例应用程序可能会有所帮助: https://github.com/n0ne/Uploadify-Carrierwave-Rails-3.2.3/blob/master/app/views/pictures/index.html.erb
还要检查此应用程序中的控制器解决方案
确实是最简单的方法。不要为更改标题而烦恼。
确保您拥有:
<%= 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);
}
});
评论
对于那些确实需要非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();
评论
哎呀。。
我在应用程序.js中错过了以下行
//= require jquery_ujs
我更换了它,它的工作..
=======更新=========
5 年后,我又遇到了同样的错误,现在我有了全新的 Rails 5.1.6,我又找到了这篇文章。就像生命的循环一样。
现在的问题是:Rails 5.1 默认删除了对 jquery 和 jquery_ujs 的支持,并添加了
//= require rails-ujs in application.js
它执行以下操作:
- 强制各种操作的确认对话框;
- 从超链接发出非 GET 请求;
- 使表单或超链接与 Ajax 异步提交数据;
- 在表单提交时自动禁用提交按钮,以防止双击。 (来自:https://github.com/rails/rails-ujs/tree/master)
但是为什么它不包括ajax请求的csrf令牌呢?如果有人对此有详细的了解,请评论我。我很感激。
无论如何,我在我的自定义 js 文件中添加了以下内容以使其工作(感谢其他答案来帮助我达到此代码):
$( document ).ready(function() {
$.ajaxSetup({
headers: {
'X-CSRF-Token': Rails.csrfToken()
}
});
----
----
});
评论
jquery_ujs
您可以像下面这样全局编写它。
普通 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'))
}
这里得票最高的答案是正确的,但如果你正在执行跨域请求,则不会起作用,因为除非你明确告诉jQuery传递会话cookie,否则会话将不可用。操作方法如下:
$.ajax({
url: url,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
},
xhrFields: {
withCredentials: true
}
});
评论
- 确保你的布局中有
<%= csrf_meta_tag %>
- 添加 a 以在 ajax 请求中包含 csrf-token 以设置标头。这仅对请求是必需的。
beforeSend
post
读取 csrf-token 的代码可在 中找到,因此恕我直言,最简单的方法是使用它,如下所示:rails/jquery-ujs
$.ajax({
url: url,
method: 'post',
beforeSend: $.rails.CSRFProtection,
data: {
// ...
}
})
评论
headers: { 'X-CSRF-Token': Rails.csrfToken() }
我正在使用 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 将无法工作,因此如果您看到此错误,这是另一个可能的原因。
评论
如果您不使用 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
import 'jquery.csrf'
我在这个问题上挣扎了好几天。任何 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 令牌错误都退出了。
希望这能帮助到其他也在用头撞墙的人。哈哈
在 2023 年升级到 Rails 7 后,由于某种原因我遇到了这个问题。也许我使用的是普通的jQuery,而不是jQuery的某些rails变体,或者任何“UJS”。
通过将此添加到我的特定于页面的 Javascript 代码中来修复它:
// Add the CSRF token to all ajax requests
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
(我已经在我的html布局的顶部)<%= csrf_meta_tags %>
我的普通jQuery Ajax代码如下所示:
var jqxhr = $.post( "something/example", { color: 'red' })
.done(function(data) {
console.log( "Ajax success:");
console.log( data );
})
.fail(function(data) {
console.log( "Ajax error:");
console.log( data );
})
.always(function() {
console.log( "Ajax finished" );
});
评论