web-dev-qa-db-ja.com

禁止(403)CSRF検証に失敗しました。要求は中止されました。 {%csrf_token%}を使用しても

Djangoでログインしようとしていますが、このエラーが発生します。CSRFのドキュメントを確認してください。何も機能しません。

HTMLは次のとおりです。

<body>
  <section class="container">
    <div class="login">
      <h1>Login to Web App</h1>

      {% if form.errors %}
        <p class="error">Lo sentimos, la combinacion de usuario y contrasena no es correcta!</p>
      {% endif %}  

      <form action="/accounts/auth/" method="post">
      {% csrf_token %}  
      <input type='hidden' name='csrfmiddlewaretoken' value='randomchars'/>

        <p><input name="username" type="text" name="login" value="" placeholder="Username"></p>

        <p><input name="password" type="password" name="password" value="" placeholder="Password"></p>

        <p class="submit"><input type="submit" name="commit" value="Login"></p>
      </form>
    </div>
</body>

上記のように、{%csrf_token%}を使用し、インストールしたアプリに「Django.middleware.csrf.CsrfViewMiddleware」があります。

私の見解は次のとおりです。

from Django.http import HttpResponse,HttpResponseRedirect
from Django.template.loader import get_template 
from Django.template import Context
from datetime import datetime
from Django.shortcuts import render_to_response
from Django.http import HttpResponseRedirect
from Django.contrib import auth
from Django.core.context_processors import csrf

from models import *
from Django.shortcuts import get_object_or_404
from forms import *
from Django.template.context import RequestContext
from Django.contrib.auth.decorators import login_required
from Django.contrib.auth import authenticate, login

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response('login.html', c)    


def auth_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        auth.login(request.user)
        return HttpResponse('/accounts/loggedin') 
    else:
        return HttpResponse('/accounts/invalid')

{%csrf_token%}を使用しない他のHTMLファイルにリダイレクトします。

17
BismarthSantana

理論


Csrf保護を機能させるには、いくつかのことが必要です( docs を確認してください):

  1. ブラウザーはサーバーからのCookieを受け入れる必要があります
  2. _Django.middleware.csrf.CsrfViewMiddleware'_にミドルウェアとして '_settings.py_が含まれていることを確認してください(保護する特定のビューでデコレーターcsrf_protect()を使用することもできます)
  3. _Django.core.context_processors.csrf_からコンテキストマネージャーにcsrfトークンを渡すようにしてください。

ページをロードしたら、お気に入りのブラウザを使用してページソースを見てください。テンプレートhtmlファイルを開かずに、フォームを含むビューを指すURLを開きます。 _{% csrf_token %}_を配置した場所を見てください。のようなものを見たら

_<input type='hidden' name='csrfmiddlewaretoken' value="jdwjwjefjwdjqwølksqøwkop2j3ofje" />
_

大丈夫です。

一方、NOTPROVIDEDを見ると、csrfトークンの作成中に問題が発生しています。ソースコード(_context_processors.py_および_csrf.py_)を調べると、次のことがわかります。

  • csrf(request)は、get_token(request)がNoneを返す場合、_{'csrf_token': 'NOTPROVIDED'}_を返します。
  • get_token(request)request.META.get("CSRF_COOKIE", None)を返します。

これは、Cookieが正常に作成されなかった場合にNoneを返すことを意味すると思います。

修正する


あなたにとって、これはあなたが最初に置き換える必要があることを意味します

_<form action="/accounts/auth/" method="post" {% csrf_token %}>
_

_<form action="/accounts/auth/" method="post">
{% csrf_token %}
(...)
</form>
_

Csrfフィールドは、inside_<form>...</form>_ではなく、_<form>_の内側にしたいです。コードは現時点では、次のように変換されます

_<form action="/accounts/auth/" method="post" <input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />>
_

そして私たちはむしろ

_<form action="/accounts/auth/" method="post">
<input type='hidden' name='csrfmiddlewaretoken' value='randomchars' />
_

その後-ソースコードを見て、csrfフィールドが見つかるかどうかを確認します。あなたがそれを見ることができれば、すべてが理論的に機能するはずです。

ブラウザでcsrf Cookieが設定されていることも確認できます。 ChromeでWebページを右クリックし、_Insepect Element_を選択します。 Resourcesタブを選択し、Cookieをクリックします。そこにCookie名csrftokenが見つかるはずです。

それでも問題が解決しない場合は、_settings.py_のミドルウェアTupleを再確認し、上記のようにブラウザーがサーバーからcookierを受け入れることを再確認してください。

21
Steinar Lima

ブラウザのキャッシュをクリアして、再試行してください。キャッシュCookieに保存されているCSRFトークンを使用している可能性があります。

2