警告:CSRFトークン認証レールを検証できません


238

AJAXを使用してビューからコントローラーにデータを送信していますが、次のエラーが発生しました。

警告:CSRFトークンの信頼性を確認できません

このトークンをデータとともに送信する必要があると思います。

誰でもこれを行う方法を知っていますか?

編集:私の解決策

これを行うには、AJAXポストに次のコードを挿入します。

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

7
あなたは持っているん<csrf_meta_tag%=%>レイアウトのヘッダに?
アナトリー

はい、このように:<%= csrf_meta_tags%>
kbaccouche '26 / 08/26

6
あなたは持っているんjqueryのは、レール AJAXクライアント側の機能を提供するライブラリを?
アナトリー

2
そしてHAMLの方法は "= csrf_meta_tags"を追加することです
Ege Akpinar

素敵な質問、質問ありがとう
AMIC MING

回答:


374

これを行う必要があります:

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

使用できるすべてのリクエストでトークンを送信するには:

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

5
ありがとう!魅力のように私のために働いた!
Misha Moroshko

35
Railsチームが提供するjQuery UJSライブラリは、CSRFトークンをjQuery AJAXリクエストに自動的に追加します。READMEには、セットアップ方法の説明が含まれています。github.com/rails/jquery-ujs/blob/master/src/rails.js#L91
James Conroy-Finn

1
$ .ajaxSetup関数を使用して、すべてのリクエストのヘッダーを一度に設定できることに注意してください。
Pieter Jongsma 2013

1
優れた!この答えをしばらく探していました。シームレスに動作します。ありがとう!
cassi.lup 2013

4
注意として、上記のようにjQuery UJSを使用している場合は、rails-ujs includeがjquery includeのに来るようにする必要があります。そうしないと、opと同じエラーで失敗します。
Topher Fangio 2017

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

7
各ajaxコマンドに対してこれを行う代わりに、$ .ajaxSetup()にヘッダーを追加できます。
スコットマクミリン

1
この回答の使用をお勧めします ...
opsidao

14
私はJavaScriptでERBを使用するアプローチが本当に好きではありません。
ラディハウンド2012

これにより、ERBを使用してJavaScriptを生成する必要があり、非常に制限されます。ERBが適している場所があったとしても、そうでない場所があり、トークンを取得するためだけに追加することは無駄です。
sockmonk 14

22

私が正しく覚えている場合は、この問題を取り除くために、フォームに次のコードを追加する必要があります。

<%= token_tag(nil) %>

パラメータを忘れないでください。


8
実際には、次のようになります<%= token_tag(nil) %>。次に、自動生成されたトークンを取得します。
-szeryf

15

確かに最も簡単な方法。ヘッダーの変更を気にしないでください。

次のことを確認してください。

<%= 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);
    }
});

非表示の入力フィールドを入力フォームに追加すると、問題が解決しました。
Teemu Leisti 2014

これは、Railsのフォームヘルパーを使用すると自動的に行われます。
Jason FB

13

古いアプリから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リクエストでリセットされていました。上記のコードを追加すると、その問題は解決しました。


10
  1. <%= csrf_meta_tag %>レイアウトにあることを確認してください
  2. beforeSendajaxリクエストにcsrf-tokenを含めるためにa を追加して、ヘッダーを設定します。これはpostリクエストにのみ必要です。

csrf-tokenを読み取るコードはで使用できるrails/jquery-ujsため、次のように、それを使用するのが最も簡単です。

$.ajax({
  url: url,
  method: 'post',
  beforeSend: $.rails.CSRFProtection,
  data: {
    // ...
  }
})

Railsにすでに含まれているものを再実装せずにシンプル。これが選択された答えになるはずです。
jiehanzheng 2017

Rails 5.1でも動作します:headers: { 'X-CSRF-Token': Rails.csrfToken() }
olhor '15年

@nathanvda、たぶん、あなたは、この類似した質問に答えることができます。stackoverflow.com/questions/50159847/...


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

この非常によく似た質問に答えてもらえますか?stackoverflow.com/questions/50159847/…–

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

コーヒースクリプト:

  $('#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'))
  }

5

おっとっと..

私のapplication.jsで次の行を逃しました

//= require jquery_ujs

私はそれを交換し、その働きをしました。

=======更新済み=========

5年後、私は同じエラーで戻ってきました、今私は真新しいRails 5.1.6を持っています、そして私はこの投稿を再び見つけました。まるで人生の輪のようです。

今問題は何でした:Rails 5.1は デフォルトでjqueryjquery_ujsのサポートを削除し、追加しました

//= require rails-ujs in application.js

次のことを行います。

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

これも私がやらなければならないことでした。これが発生した理由は、既存のRailsアプリをゆっくりと置き換えるためにReactアプリを作成しているためです。既存のアプリでは多くのJavaScriptノイズが発生しているため、別のJavaScriptファイルにアクセスする別のレイアウトを作成しましたが、を含めることができませんでしたjquery_ujs。それがトリックでした。
ウィリアムジャッド2017

1
はい、時々リワークするときにそれを見逃した場合、何かをリファクタリングします。何が悪いのかを見つけるのは難しいです。それを機能させるために手動で何も実行していないため、Railsはそれを自動的に含めます。すでにそこにあると思います。そのような社会的なQn / Ansサイトをありがとう
Abhi

:たぶん、あなたは、この類似した質問に答えることができstackoverflow.com/questions/50159847/...

4

jQueryを使用せず、リクエストにフェッチ 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)
    })

この非常によく似た質問に答えてもらえますか?stackoverflow.com/questions/50159847/…–

4

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


5.1でwebpackを使うと、//= require jquery.csrfうまくいきませんか?代わりに、私はその中にpack jsファイルを使用しimport 'jquery.csrf'ました。ビューにこれをpackタグとともに含める必要ありませ
Damien JustinŠutevski17年

3

フォームでトークンを生成するためにjQueryでJavaScriptを使用している場合、これは機能します。

<input name="authenticity_token" 
       type="hidden" 
       value="<%= $('meta[name=csrf-token]').attr('content') %>" />

もちろん、<%= csrf_meta_tag %>Rubyレイアウトにを含める必要があります。


2

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

6
これはセレクターにjQueryを使用しませんか?
Yule

2

私はこの問題に何日も苦労しました。GET呼び出しはすべて正常に機能していましたが、すべてのPUTで「CSRFトークンの信頼性を検証できません」というエラーが生成されました。SSL証明書をnginxに追加するまで、私のウェブサイトは問題なく動作していました。

私は最終的に私の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トークンエラーが終了します。

うまくいけば、これが壁に頭をぶつけている他の誰かを助けるでしょう。ははは



0

私は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

クッキーをオフにしていたので、結局失敗しました。CSRFはCookieが有効になっていないと機能しないため、このエラーが表示された場合、これは別の考えられる原因です。


とても助かります!
joehwang 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.