web-dev-qa-db-ja.com

AJAXフォームのリクエストを送信する際にCSRFトークンを渡す方法は?

私はScala Play!2.6 Frameworkを使用していますが、それは問題ではないかもしれません。Javascriptルーティングを使用しています-それはうまくいくようですが、問題があります。 CSRFトークンを使用して、レンダリング時にこれを生成するフォーム:

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

そして、大まかに、私のAJAXは次のとおりです。

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    textvalue: $('#sometext').val()
   }
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});

しかし、これを投稿すると、サーバーから不正な応答が返され、IntelliJのコンソールからCSRFチェックが失敗していることが通知されます。リクエストでCSRFトークンをどのように渡すのですか?

11
NateH06

数時間これと戦い、 subject でPlayの頻繁に欠落するコンテキストドキュメントを解読しようとした後、わかりました。

したがって、彼らのドキュメントから:

ブラウザ以外のリクエストを簡単に保護できるようにするため、PlayはヘッダーにCookieがあるリクエストのみをチェックします。 AJAXを使用してリクエストを行う場合、CSRFトークンをHTMLページに配置し、Csrf-Tokenヘッダーを使用してリクエストに追加できます。

そして、コードも例もありません。 Playに感謝します。とてもわかりやすい。とにかく、ここに方法があります:

あなたのview.html.formTemplateにIntelliJで書くかもしれません:

@()
<form method="post" id="myForm" action="someURL">

@helper.CSRF.formField  <!-- This auto-generates a token for you -->
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

そして、これはクライアントに配信されると次のようにレンダリングされます。

<form method="post" id="myForm" action="someURL">

<input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">
  <input type="text" id="sometext">
  <button type="submit"> Submit! </button>

</form>

OK、ほぼそこに、今、私たちはAJAX呼び出しを作成する必要があります。私はすべてを別のmain.jsファイルに持っていますが、必要に応じてこれをview.html.formTemplateに入れることもできます。

$(document).on('submit', '#myForm', function (event) {

 event.preventDefault();
   var data = {
    myTextToPass: $('#sometext').val()
   }
 // LOOK AT ME! BETWEEN HERE AND
 var token =  $('input[name="csrfToken"]').attr('value')
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('Csrf-Token', token);
        }
    });
// HERE
 var route = jsRoutes.controllers.DashboardController.postNewProject()
 $.ajax({
    url: route.url,
    type: route.type,
    data : JSON.stringify(data),
    contentType : 'application/json',
    success: function (data) { ...      },
    error: function (data) { ...  }
        })

});

次の行を使用します。var token = $('input[name="csrfToken"]').attr('value')フォームフィールドで自動生成されたCSRFトークンを抜き取り、Javascriptで使用されるvarの値を取得しています。

AJAX=のすべてからの他の重要なチャンクはここにあります:

$.ajaxSetup({
            beforeSend: function(xhr) {
                xhr.setRequestHeader('Csrf-Token', token);
            }
        });

$.ajaxSetupを使用して、ヘッダーの内容を設定できます。これは、ドキュメントから推測する必要があるものです。

csrf-Tokenヘッダーを使用してリクエストに追加します。

がんばろう!これが明確かどうかを教えてください。


lusca を使用する場合は、X-CSRF-Tokenの代わりにCsrf-Tokenを使用します。

18
NateH06

_Csrf-Token_ヘッダーを使用してリクエストに追加します。

ヘッダー名をありがとうNateH06!私はajax関数呼び出しで「削除」ボタンのcsrfトークンを送信しようとしていましたが、次のことにこだわっていました。

_@import helper._
....
<button id="deleteBookBtn" class="btn btn-danger"
        data-csrf-name="@helper.CSRF.getToken.name"
        data-csrf-value="@helper.CSRF.getToken.value"
        data-delete-url="@routes.BooksController.destroy(book.id)"
        data-redirect-url="@routes.HomeController.index()">Delete</button>
_

プレイ2.6でもCSPが設定されているため、onclick()イベント内にオンラインjsを追加できませんでした。

次のコンテンツセキュリティポリシーディレクティブ「default-src 'self'」に違反しているため、インラインイベントハンドラーの実行を拒否しました。

そして、JSファイルで:

_function sendDeleteRequest(event) {
  url = event.target.getAttribute("data-delete-url")
  redirect = event.target.getAttribute("data-redirect-url")
  csrfTokenName = event.target.getAttribute("data-csrf-name")
  csrfTokenValue = event.target.getAttribute("data-csrf-value")
  $.ajax({
    url: url,
    method: "DELETE",
    beforeSend: function(request) {
      //'Csrf-Token' is the expected header name, not $csrfTokenName
      request.setRequestHeader(/*$csrfTokenName*/'Csrf-Token', csrfTokenValue);
    },
    success: function() {
      window.location = redirect;
    },
    error: function() {
      window.location.reload();
    }
  })
}

var deleteBookBtn = document.getElementById("deleteBookBtn");
if(deleteBookBtn) {
    deleteBookBtn.addEventListener("click", sendDeleteRequest);
}
_

ヘッダー名を_'Csrf-Token'_に設定すると、ajax呼び出しは完全に機能します!

2
inieto

JSPから

<form method="post" id="myForm" action="someURL">
    <input name="csrfToken" value="5965f0d244b7d32b334eff840...etc" type="hidden">    
</form>

これは3時間苦労した後、私のために働いた最も簡単な方法です、このような入力隠しフィールドからトークンを取得し、AJAXリクエストを次のようにヘッダーで渡す必要があります:-

JQueryから

var token =  $('input[name="csrfToken"]').attr('value'); 

プレーンJavascriptから

var token = document.getElementsByName("csrfToken").value;

最終AJAXリクエスト

$.ajax({
      url: route.url,
      data : JSON.stringify(data),
      method : 'POST',
      headers: {
                    'X-CSRF-Token': token 
               },
      success: function (data) { ...      },
      error: function (data) { ...  }

});

これで、web configでcrsfセキュリティを無効にする必要はありません。また、コンソールで405(Method Not Allowed)エラーは発生しません。

これが人々を助けることを願って.. !!

1
MOnkey

正しいトークンが表示されない理由を理解しようとしてグーグルをしている他の人に役立つ場合.... Playバックエンド/ Reactフロントエンドの組み合わせで同じ問題に苦しんでいます。 token-in-htmlpageテクニックを(簡単に)使用できません。最終的に、Cookieに現在のトークンを設定するための別のソリューションに出会いました...

play.filters.csrf {
  cookie.name = "csrftoken"
}

application.confにcsrftoken Cookieがトークンに設定されます。次に、 https://www.npmjs.com/package/js-cookie を使用して、JSコードの値を取得し、リクエストヘッダーに送り返します。コードは=なので、 React OPについてはjQueryではなく、問題を混乱させたくない。

0
fredex42

headersオプションでCsrf-Tokenヘッダーを追加できます。

$.ajax({
    url: '@routes.MyController.myPostAction()',
    method: 'post',
    headers: {
        'Csrf-Token': '@play.filters.csrf.CSRF.getToken.map(_.value)'
    },
    data: {
        name: '@name'
    },
    success: function (data, textStatus, jqXHR) {
        location.reload();
    },
    error: function (jqXHR, textStatus, errorThrown) {
        debugger;
    }
});
0
Aha00a

Play Framework 2.6 Documentation に記載されているように、Playによって生成されたトークンを使用して 'Csrf-Token'ヘッダーを設定できます。

AJAXでリクエストを行う場合、CSRFトークンをHTMLページに配置し、Csrf-Tokenヘッダーを使用してリクエストに追加できます。

Scala-Template内では、@helper.CSRF.getToken.valueを使用してトークン値を取得できます

jQuerys Documentation に従って、 ajaxSetup を使用してjQueryを設定することにより、すべてのAjaxリクエストに対して1回設定できます。

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('Csrf-Token', '@helper.CSRF.getToken.value');
  }
});

または、次のようにheadersオブジェクトを設定して、すべてのリクエストにヘッダーを設定します。

$.ajax({
  url: route.url,
  ...
  headers: {
    'Csrf-Token': '@helper.CSRF.getToken.value'
  }
});
0
bmenzel