我用AJAXand发送数据从视图到控制器,我得到了这个错误:

警告:无法验证CSRF令牌的真实性

我想我必须用数据发送这个令牌。

有人知道我该怎么做吗?

编辑:我的解决方案

我通过在AJAX帖子中放入以下代码来做到这一点:

headers: {
  'X-Transaction': 'POST Example',
  'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},

当前回答

如果你没有使用jQuery,而是使用类似于获取API的请求,你可以使用下面的方法来获取csrf-token:

文档。querySelector(“元[name =“csrf-token”]”)。getAttribute(“内容”)

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)
    })

其他回答

我使用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将无法工作,因此如果您看到此错误,这是另一个可能的原因。

最好的方法实际上是使用<%= form_authenticity_token。To_s %>直接在rails代码中打印令牌。你不需要像其他文章提到的那样使用javascript来搜索dom中的csrf令牌。只需添加标题选项如下;

$.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) %>"
})

哎呀. .

我在我的application.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):

但为什么它不包括csrf令牌ajax请求?如果有人知道这个细节,请评论我。我很感激。

无论如何,我在我的自定义js文件中添加了以下内容以使其工作(感谢其他帮助我实现此代码的答案):

$( document ).ready(function() {
  $.ajaxSetup({
    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'))
  }