1. ホーム
  2. Django

Djangoは、フォームを送信するときに403エラーに遭遇しました。CSRF 検証に失敗しました。

2022-03-01 19:36:09

Djangoフレームワークでフォーム送信を学習中、以下の内容で403エラーに遭遇しました。

Forbidden (403)
CSRF verification failed. request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.
Help
Reason given for failure:
    CSRF cookie not set.
    
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly, For POST forms, you need to ensure:
1. Your browser is accepting cookies.
The view function passes a request to the template's render method. 3.
3. In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data. 5.
The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the After logging in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.



プロンプトに従って、順番にチェックスルーしてください。

1.私のブラウザはCookieがオンになっていますが、問題ありません。

2. 私のview.pyのコードは以下のようなものです。

#coding=utf-8
from django.shortcuts import render, render_to_response

#form
class UserForm(forms.Form):
    username = forms.CharField(label='username',max_length=20)
    password = forms.CharField(label='Password',widget=forms.

def register(request):
    if request.method == 'POST':
        uf = UserForm(request.POST)
        if uf.is_valid():
            #Get form data
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            #Add to database
            User.objects.create(username= username,password=password)
            return HttpResponse('Register success!!!')
        else:
            return HttpResponse('Register failed!!!')
    else:
        uf = UserForm()
        return render_to_response('register.html', context=RequestContext(request, {'uf':uf}))


このコードはウェブからコピーしたもので、ここではRequestContextを使用しており、RequestContextにリクエストを渡していますが、これは問題ないようです。

3. 私のテンプレートの中身はこんな感じです。

<?xml version="1.0" encoding="UTF-8"? >
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Register</title>
</head>

<body>
<h1> Registration page: </h1>
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {
{uf.as_p}}
    <input type="submit" value = "register" />
</form>
<br>
<a href="/login/">login</a>
</body>
</html>

このテンプレートでは "{% csrf_token %}" も使用していますが、これについては問題がないようです。

4. ミドルウェアのCsrfViewMiddlewareは、プロジェクト作成時にデフォルトで追加されますが、それで問題ありません。

5. 最初にフォームが送信されたときに403エラーが発生し、フォールバックがないため、無視できます。

さらに2点確認しました。

1. バックエンドサーバーは以下のようなログを出力しています。

UserWarning: テンプレートで {% csrf_token %} が使用されましたが、コンテキストがその値を提供しませんでした。これは通常、RequestContext を使用していないことが原因です。

2. ブラウザのCookieを確認する

私はChromeを使っていて、プラグインのWeb Developerをインストールしたのですが、そのページには本当にクッキーが設定されていないことが確認できます。


ページのクッキーがうまく設定されていないことがわかりますが、クッキーの設定はチェックリストの項目2で行っています。Django のローカルインストールはバージョン 1.10 で、このコードは 1.10 より前のバージョンで実行されるようにコピーされています。

def register(request):
    if request.method == 'POST':
        uf = UserForm(request.POST)
        if uf.is_valid():
            #Get form data
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            #Add to database
            User.objects.create(username= username,password=password)
            return HttpResponse('Register success!!!')
        else:
            return HttpResponse('Register failed!!!')
    else:
        uf = UserForm()
        return render(request, 'register.html', Context({'uf':uf}))


この結果は正常に動作し、Web Developer を通して、ページによってクッキー "csrftoken" が正常に設定されたことが確認できます。