2011-10-19 14 views
9

奇妙に聞こえますが、フォームを使用せずにJavascript(例:AJAX)を使ってコンテンツを投稿するシナリオについては、奇妙に聞こえるかもしれません(表面から複数のコンテンツを読むことができます)。Django CSRF形式のないトークン

ここで、csrf_tokenテンプレートタグを配置する必要がありますか?私はすでにAJAX修正を追加しました: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

...しかし、私は "CSRF検証に失敗しました。要求が中止されました。" 404エラー。

答えて

13

AJAXリクエストにカスタムHTTPヘッダーX-CSRFTokenを設定する必要があります。参照:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

既にこのアドバイスに従っている場合は、動作しているはずです。 Firebugのようなものを使って、送信されているリクエストを監視し、ヘッダーを検査して、カスタムヘッダーが本当に渡されていることを確認します。そうでない場合は、実装を再度確認して、ドキュメントの説明どおりに実装していることを確認してください。

も注意してください。

ためのjQuery 1.5で導入されたバグのため、上記の例では、そのバージョンでは正しく動作しません。少なくともjQuery 1.5.1を実行していることを確認してください。

+0

Firebugのヒント。それはそれを作った。クッキーにトークンが表示され、リクエストにトークンが表示されます。問題は私のアプリのこの部分ではなかったとわかりました。 私の質問に答えるには:このPre-AJAX機能のため、テンプレートタグフィールドは不要です。右? –

+1

はい、私がドキュメントを正しく理解している場合、Djangoはテンプレートタグを完全に上回り、CSRFトークンを処理するためのクッキーを優先しています。 –

0

一つCSRFトークンが(すなわち、毎回ログインする)すべてのセッションに割り当てられている:

$.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' },}); 

は、より参照してください。したがって、ユーザが入力したデータを取得し、csrf_protectデコレータによって保護されている関数にajax呼び出しとして送信する前に、このデータをユーザから取得する前に呼び出されている関数を探してみてください。例えば。ユーザーがデータを入力するテンプレートをレンダリングする必要があります。そのテンプレートはある機能によってレンダリングされています。この関数では、次のようにcsrfトークンを取得できます。csrf = request.COOKIES ['csrftoken']問題のテンプレートがレンダリングされているコンテキスト辞書にこのcsrf値を渡します。そのテンプレートで、この行を書いてください:今あなたのjavascript関数で、ajaxリクエストを作成する前に、次のように書いてください:var csrf = $( '#csrf')。val()これはテンプレートに渡されたトークンの値を取り出し、 csrf。今度はあなたのポストデータでajaxを呼び出す際にもこの値を渡します: "csrfmiddlewaretoken":csrf

これはdjangoフォームを実装していなくても機能します。

実際、ここでの論理は次のとおりです。要求から取得できるトークンが必要です。だから、ログインした直後に呼び出されている関数を調べる必要があります。このトークンを取得したら、別のajax呼び出しを行ってそれを取得するか、ajaxでアクセス可能なテンプレートに渡します。

0

フォームなしで投稿する場合は、CSRFトークンを設定するには2つの手順があります。

1)Cookieからcsrftokenを入手してください。

2)csrftokenを取得したら、(データをPOSTする前に)csrftokenでヘッダーを設定する必要があります。


1)Cookieからcsrftokenを入手してください。

// Function to GET csrftoken from Cookie 
function getCookie(name) { 
    var cookieValue = null; 
    if (document.cookie && document.cookie !== '') { 
     var cookies = document.cookie.split(';'); 
     for (var i = 0; i < cookies.length; i++) { 
      var cookie = jQuery.trim(cookies[i]); 
      // Does this cookie string begin with the name we want? 
      if (cookie.substring(0, name.length + 1) === (name + '=')) { 
       cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
       break; 
      } 
     } 
    } 
    return cookieValue; 
} 

var csrftoken = getCookie('csrftoken'); 

2)あなたはcsrftokenを持っていたら、あなたはデータをPOSTする前に、あなたはcsrftokenとヘッダーを(設定する必要があります)。

function csrfSafeMethod(method) { 
    // these HTTP methods do not require CSRF protection 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 

// Function to set Request Header with `CSRFTOKEN` 
function setRequestHeader(){ 
    $.ajaxSetup({ 
     beforeSend: function(xhr, settings) { 
      if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 
       xhr.setRequestHeader("X-CSRFToken", csrftoken); 
      } 
     } 
    }); 
} 

function postSomeData() { 
    ..... 
    setRequestHeader(); 

    $.ajax({ 
     dataType: 'json', 
     type: 'POST', 
     url: "/url-of-some-api/", 
     data: data, 
     success: function() { 
      alert('success'); 
     }, 
     error: function() { 
      alert('error'); 
     } 
    }); 

}