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

kba*_*che 232 jquery ruby-on-rails csrf

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

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

我想我必须发送带有数据的令牌.

有谁知道我该怎么做?

编辑:我的解决方案

我通过将以下代码放在AJAX帖子中来完成此操作:

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

小智 366

你应该做这个:

  1. 确保<%= csrf_meta_tag %>您的布局中有

  2. 添加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);
  }
});
Run Code Online (Sandbox Code Playgroud)

要在所有请求中发送令牌,您可以使用:

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});
Run Code Online (Sandbox Code Playgroud)

  • Rails团队提供的jQuery UJS库自动将CSRF令牌添加到jQuery AJAX请求中.README包含有关如何进行设置的说明.https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L91 (33认同)
  • 谢谢!像魅力一样为我工作! (4认同)
  • 需要注意的是,如果您正在使用上面建议的jQuery UJS,则需要确保rails-ujs包含在*jquery include之后*或者它将失败并出现与op相同的错误. (3认同)

ADA*_*DAM 31

实现此目的的最佳方法实际上就是<%= 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) %>"
})
Run Code Online (Sandbox Code Playgroud)

  • 我真的不喜欢在javascript中使用ERB的方法. (14认同)
  • 您可以将**标头**添加到[$ .ajaxSetup()](http://api.jquery.com/jQuery.ajaxSetup/),而不是为每个ajax命令执行此操作. (7认同)

aur*_*bee 22

如果我没记错的话,你必须在表单中添加以下代码,以解决这个问题:

<%= token_tag(nil) %>
Run Code Online (Sandbox Code Playgroud)

不要忘记参数.

  • 实际上,这应该是:`<%= token_tag(nil)%>`.然后你得到自动生成的令牌. (8认同)

小智 15

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

确保你有:

<%= csrf_meta_tag %> in your layouts/application.html.erb
Run Code Online (Sandbox Code Playgroud)

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

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


Dan*_*nny 13

从较旧的应用程序升级到rails 3.1,包括csrf元标记仍然没有解决它.在rubyonrails.org博客上,他们提供了一些升级提示,特别是这一行jquery应该放在你的布局的head部分:

$(document).ajaxSend(function(e, xhr, options) {
 var token = $("meta[name='csrf-token']").attr("content");
  xhr.setRequestHeader("X-CSRF-Token", token);
});
Run Code Online (Sandbox Code Playgroud)

取自这篇博文:http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails.

在我的情况下,会话正在重置每个ajax请求.添加上面的代码解决了这个问题.


nat*_*vda 10

  1. 确保<%= csrf_meta_tag %>您的布局中有
  2. 添加a beforeSend以在ajax请求中包含csrf-token以设置标头.这仅适用于post请求.

读取csrf-token的代码可以使用rails/jquery-ujs,因此最简单的方法是使用它,如下所示:

$.ajax({
  url: url,
  method: 'post',
  beforeSend: $.rails.CSRFProtection,
  data: {
    // ...
  }
})
Run Code Online (Sandbox Code Playgroud)


sci*_*tai 6

我只是想把这个链接到这里,因为这篇文章有你想要的大部分答案,而且它也很有趣

http://www.kalzumeus.com/2011/11/17/i-saw-an-extremely-subtle-bug-today-and-i-just-have-to-tell-someone/


Ben*_*key 6

此处的最高投票答案是正确的,但如果您执行跨域请求将无法工作,因为除非您明确告诉jQuery传递会话cookie,否则会话将不可用.以下是如何做到这一点:

$.ajax({ 
  url: url,
  type: 'POST',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  },
  xhrFields: {
    withCredentials: true
  }
});
Run Code Online (Sandbox Code Playgroud)


svn*_*vnm 6

如果您不使用 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)
    })
Run Code Online (Sandbox Code Playgroud)


Abh*_*bhi 5

哎呀..

我错过了 application.js 中的以下行

//= require jquery_ujs
Run Code Online (Sandbox Code Playgroud)

我更换了它,它的工作原理..

======== 更新 ==========

5 年后,我又回到了同样的错误,现在我有了全新的Rails 5.1.6,我又找到了这篇文章。就像生活圈一样。

现在的问题是: Rails 5.1默认删除了对jqueryjquery_ujs的支持,并添加了

//= require rails-ujs in application.js
Run Code Online (Sandbox Code Playgroud)

它执行以下操作:

  1. 各种动作的强制确认对话框;
  2. 从超链接发出非 GET 请求;
  3. 使表单或超链接与 Ajax 异步提交数据;
  4. 提交按钮在表单提交时自动禁用以防止双击。(来自:https : //github.com/rails/rails-ujs/tree/master

但是为什么它不包括 ajax 请求的 csrf 令牌?如果有人详细了解这一点,请评论我。我很感激。

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

$( document ).ready(function() {
  $.ajaxSetup({
    headers: {
      'X-CSRF-Token': Rails.csrfToken()
    }
  });
  ----
  ----
});
Run Code Online (Sandbox Code Playgroud)


Che*_*ian 5

您可以像下面这样全局地编写它。

普通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'))}
    });
});
Run Code Online (Sandbox Code Playgroud)

咖啡脚本:

  $('#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'))
  }
Run Code Online (Sandbox Code Playgroud)