web-dev-qa-db-ja.com

「AJAX in Django

私は次のようなパラメータを投稿しようとします

 jQuery.ajax(
        {
            'type': 'POST',
            'url': url,
            'contentType': 'application/json',
            'data': "{content:'xxx'}",
            'dataType': 'json',
            'success': rateReviewResult 
        }
    );

ただし、Django return Forbidden 403. CSRF verification failed. Request aborted. 使っています 'Django.middleware.csrf.CsrfViewMiddleware'そして、セキュリティを損なうことなくこの問題を防ぐ方法を見つけることができませんでした。

57
brsbilgic

AJAXリクエストを送信するには、2つの異なる方法があります。

  1. ビューにcsrfトークンをチェックしないように指示するため。これは、次のようにデコレーター@csrf_exemptを使用して実行できます。

    from Django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def your_view_name(request):
        ...
    
  2. 各AJAXリクエストにcsrfトークンを埋め込むには、jQueryの場合:

    $(function () {
        $.ajaxSetup({
            headers: { "X-CSRFToken": getCookie("csrftoken") }
        });
    });
    

    getCookie関数は、cookieからcsrfトークンを取得します。次の実装を使用します。

    function getCookie(c_name)
    {
        if (document.cookie.length > 0)
        {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1)
            {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start,c_end));
            }
        }
        return "";
     }
    

    また、jQuery プラグインを持っています クッキーにアクセスするために、そのようなもの:

    // set cookie
    $.cookie('cookiename', 'cookievalue');
    // read cookie
    var myCookie = $.cookie('cookiename');
    // delete cookie
    $.cookie('cookiename', null);
    
86
sigurd

私が見つけた最も簡単な方法は、{{csrf_token}}データの値:

jQuery.ajax(
    {
        'type': 'POST',
        'url': url,
        'contentType': 'application/json',
        'data': {
            'content': 'xxx',
            'csrfmiddlewaretoken': '{{ csrf_token }}',
        },
        'dataType': 'json',
        'success': rateReviewResult 
    }
);
40
jerrykan

ダニエルが投稿した コード で何をすべきかを理解するには、しばらく時間がかかりました。しかし実際には、javascriptファイルの先頭に貼り付けるだけです。

私にとって、これまでの最善の解決策は次のとおりです。

  1. csrf.jsファイルを作成します

  2. 貼り付け コードcsrf.jsファイルに

  3. 必要なテンプレートのコードを参照します

    <script type="text/javascript" src="{{ STATIC_PREFIX }}js/csrf.js"></script>
    

STATIC_PREFIX/js/csrf.jsが私のファイルを指していることに注意してください。私は実際にSTATIC_PREFIX変数に{% get_static_prefix as STATIC_PREFIX %}をロードしています。


高度なヒント:テンプレートを使用しており、base.htmlのような拡張元がある場合は、そこからスクリプトを参照して、残りのファイルについてはもう心配する必要はありません。私が理解している限り、これはセキュリティ上の問題でもありません。

22
toto_tico

シンプルで短い

$.ajaxSetup({
  headers: { "X-CSRFToken": '{{csrf_token}}' }
});

OR

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
  beforeSend: function(xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", '{{csrf_token}}');
    }
  }
});

ドキュメント

9
Khaino

簡単な答えがない場合は、ヘッダーを追加する必要がありますX-CSRFToken cookieにあるajaxリクエストcsrftokenに。 JQueryは プラグイン なしではCookieを(何らかの理由で)実行しません:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

最小限のコード変更は次のとおりです。

$.ajax({
  headers: { "X-CSRFToken": $.cookie("csrftoken") },
  ...
});
4
CpILL

昨日同じ問題が発生し、それを処理する簡単な方法があれば人々に役立つと思ったので、そのためのjQueryプラグインを作成しました: jquery.djangocsrf 。すべてのリクエストにCSRFトークンを追加する代わりに、AjaxSend jQueryイベントに自身をフックし、クライアントCookieをヘッダーに追加します。

使用方法は次のとおりです。

1-含める:

<script src="path/to/jquery.js"></script>
<script src="path/to/jquery.cookie.js"></script>
<script src="path/to/jquery.djangocsrf.js"></script>

2-コードで有効にします:

$.djangocsrf( "enable" );

テンプレートが{% csrf_token %}を使用する場合、Djangoは常にCookieにトークンを追加します。テンプレートで特別なタグを使用しなくても常に追加されるようにするには、@ensure_csrf_cookieデコレーターを使用します。

from Django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def my_view(request):
    return render(request, 'mytemplate.html')

注:Django 1.6.2。

4
bfontaine

すべての回答をありがとうございます。私はDjango 1.5.1。を使用しています。パーティーに少し遅れていますが、ここに行きます。

Django project へのリンクは非常に便利であることがわかりましたが、Ajax呼び出しを行うたびに余分なJavaScriptコードを含める必要はありませんでした。

Jerrykanの応答は非常に簡潔であり、通常のAjax呼び出しに1行しか追加されないため、私はこれが好きです。 Djangoテンプレートタグが利用できない状況に関する彼のコメントの下のコメントに応じて、DOMからcsrfmiddlewaretokenをロードするのはどうですか?

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    data: { 'csrfmiddlewaretoken': token },
    dataType: 'json',
    success: function(data) { console.log('Yippee! ' + data); } 
});

2016年3月編集

この問題に対する私の過去数年間のアプローチは変わりました。次のコードを( Django docs から)main.jsファイルに追加し、すべてのページにロードします。完了したら、再びajaxを使用してCSRFトークンを心配する必要はありません。

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');
4
jbiz

含むx-csrftokenリクエストのヘッダー:

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    beforeSend : function(jqXHR, settings) {
        jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie());
    },
    data: data,
    dataType: 'json',

});
3
Hasan Ramezani

テンプレートにjsを埋め込まない場合、プラグインなしの最速のソリューションは次のとおりです。

<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>テンプレート内のscript.jsファイルへの参照の前に、csrfmiddlewaretokendata辞書に追加します。

$.ajax({
            type: 'POST',
            url: somepathname + "do_it/",
            data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
            success: function() {
                console.log("Success!");
            }
        })

Jsをテンプレートに埋め込む場合、次のように簡単です:data: {csrfmiddlewaretoken: '{{ csrf_token }}'}

2
Marek Židek

他の回答を読んだ後、誰かがまだ苦労している場合は、これを試してください:

   $.ajax({
            type: "POST",
            beforeSend: function (request)
            {
                request.setRequestHeader("X-CSRF-TOKEN", "${_csrf.token}");
            },
            url: servlet_path,
            data : data,
            success : function(result) {
            console.log("Success!");
   }
});
0
Fr333du