it-roy-ru.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')

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

16
BismarthSantana

Теория


Для того чтобы защита csrf работала, необходимо выполнить несколько действий (см. docs ):

  1. Ваш браузер должен принимать куки с вашего сервера
  2. Убедитесь, что Django.middleware.csrf.CsrfViewMiddleware' включен в качестве промежуточного программного обеспечения в settings.py (альтернативно используйте декоратор csrf_protect () для определенных представлений, которые вы хотите защитить)
  3. Убедитесь, что вы передаете токен 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 не будет успешно создан. 

Исправлять


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

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

с

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

Мы бы хотели, чтобы поле csrf находилось внутри <form>...</form>, а не inside<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 csrftoken.

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

19
Steinar Lima

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

1
Mohammad Etemaddar