Запрещено (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')

i перенаправлять на другой файл HTML, где я не использую {% csrf_token%}.

Ответ 1

Теория


Для защиты работы csrf требуется несколько вещей (посмотрите docs):

  • Ваш браузер должен принимать файлы cookie с вашего сервера.
  • Убедитесь, что у вас есть < django.middleware.csrf.CsrfViewMiddleware' в качестве промежуточного программного обеспечения в settings.py (в качестве альтернативы используйте декоратор csrf_protect() для определенных видов, которые вы хотите защитить)
  • Убедитесь, что вы передаете токен csrf из django.core.context_processors.csrf в диспетчер контекстов.

Когда вы загружаете свою страницу, посмотрите в источнике страницы, используя ваш любимый браузер. Не открывайте шаблон html файла, откройте URL-адрес, указывающий на представление, содержащее форму. Посмотрите, где вы разместили {% csrf_token %}. Если вы видите что-то вроде

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

ты должен быть в порядке.

Если вы, с другой стороны, видите NOTPROVIDED, что-то пошло не так, создавая токен csrf. Изучая исходный код (context_processors.py и csrf.py), мы можем узнать, что:

  • csrf(request) возвращает {'csrf_token': 'NOTPROVIDED'}, если get_token(request) возвращает None.
  • get_token(request) возвращает request.META.get("CSRF_COOKIE", None).

Я предполагаю, что это означает, что он вернет None, если файл cookie не будет успешно создан.

Fix


Для вас это означает, что вы должны сначала заменить

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

с

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

Мы хотели бы, чтобы поле csrf находилось внутри <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. Если вы можете это увидеть, все должно работать теоретически.

Вы также можете проверить, что cookie csrf был установлен в вашем браузере, например. в Chrome щелкните правой кнопкой мыши веб-страницу и выберите Insepect Element. Перейдите на вкладку Resources и нажмите на файлы cookie. Вы должны найти имя файла cookie csrftoken.

Если у вас все еще есть проблемы, дважды проверьте кортеж промежуточного слоя в settings.py и дважды проверьте, что ваш браузер принимает cookie с вашего сервера, как описано выше.

Ответ 2

Очистите кеш браузера и повторите попытку. Возможно, он использует маркер CSRF, сохраненный в cookie.

Ответ 3

С добавлением выше ответа, Попробуйте добавить следующие строки в представлениях

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def somathing():
   return something