4

次の状況に遭遇しました (Django1.4 と jQuery 1.7.1 を使用) を理解したいと思います: jQuery の「ajax」関数を使用してフォームを送信し、この要求が完了する前に、同じフォームを送信する別の要素をクリックしますが、 jQuery の「送信」機能を使用します。私が受け取る応答 - 403、CSRF 検証に失敗しました。もちろん、このエラーを防ぐには、複数の同時送信を無効にするだけで十分ですが (それらは単独で正常に動作します)、特定のエラーの原因を理解するのには役立ちません。

誰でもこれを説明できますか?csrf トークンはセッションごとに 1 回生成されるため、後者のリクエストでは何らかの csrf の不一致になることはありません。これは、jQuery がリクエストを処理する方法と関係がありますか?

4

2 に答える 2

0

あなたのコードに問題があると思います。Djangoコードを読むだけ


このブロックでキャッチされたエラー。

if not constant_time_compare(request_csrf_token, csrf_token):
            logger.warning('Forbidden (%s): %s',
                           REASON_BAD_TOKEN, request.path,
                extra={
                    'status_code': 403,
                    'request': request,
                }
            )
            return self._reject(request, REASON_BAD_TOKEN)

したがって、フロントエンドスクリプトは csrf_token を送信し、Cookie (ブラウザーを送信する) は等しくありません


次のコード作業

tpl

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>

<a href="javascript:" class="req1">req1</a>
<a href="javascript:" class="req2">req2</a>
<br>

<form id="foo" action="" method="POST">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit">
</form>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
    $(document).ready(function(){

        $('.req2').click(function(){
            var form1 = $.post( '', $('#foo').serialize(), function(data){console.log(data)} );
        })

        $('.req1').click(function(){
            var form1 = $.post( '', $('#foo').serialize(), function(data){console.log(data)} );
        })
    })
</script>
</body>
</html>

見る

from django import forms
from django.http import HttpResponse

from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect


class TestForm(forms.Form):
    test_field = forms.CharField()


@csrf_protect
def home(request):
    if request.method == 'POST':
        form = TestForm(request.POST)
        if form.is_valid():
            return HttpResponse('all ok')
    else: form = TestForm()

    return render(request,
        'page.html',
            {
            'form': form,
             },
    )
于 2012-07-23T21:36:39.237 に答える
0

問題は解決しました - ajax 呼び出しを担当する js スクリプトが beforeSend 関数のフォーム入力 (csrf トークンを含む) に「無効」属性を設定するという事実を見逃しました - そのような無効な属性は POST で送信されません。

于 2012-08-27T12:56:11.087 に答える