Файл cookie Django CSRF не установлен


86

Некоторое время у меня возникла проблема, у меня не установлен CSRF Cookie. Пожалуйста, посмотрите на коды ниже

Python

def deposit(request, account_num):
    if request.method == 'POST':
        account = get_object_or_404(account_info, acct_number=account_num)
        form_ = AccountForm(request.POST or None, instance=account)
        form = BalanceForm(request.POST)
        info = str(account_info.objects.filter(acct_number=account_num))
        inf = info.split()
        
        if form.is_valid():

            # cd=form.cleaned_data
            now = datetime.datetime.now()
            cmodel = form.save()
            cmodel.acct_number = account_num
            
            # RepresentsInt(cmodel.acct_number)
            cmodel.bal_change = "%0.2f" % float(cmodel.bal_change)
            cmodel.total_balance = "%0.2f" % (float(inf[1]) + float(cmodel.bal_change))
            account.balance = "%0.2f" % float(cmodel.total_balance)
            cmodel.total_balance = "%0.2f" % float(cmodel.total_balance)
            
            # cmodel.bal_change=cmodel.bal_change
            cmodel.issued = now.strftime("%m/%d/%y %I:%M:%S %p")
            account.recent_change = cmodel.issued
            cmodel.save()
            account.save()
            
            return HttpResponseRedirect("/history/" + account_num + "/")
        
        else:
            return render_to_response('history.html',
                                      {'account_form': form},
                                      context_instance=RequestContext(request))

В HTML вот код

HTML

<form action="/deposit/{{ account_num }}/" method="post">
    <table>
        <tr>
            {{ account_form.bal_change }}
            &nbsp;
            <input type="submit" value="Deposit"/>
        </tr>
        {% csrf_token %}
    </table>
</form>

Я застрял, я уже очистил файл cookie, использовал другой браузер, но файл cookie csrf не установлен.


Есть ли у вас CsrfViewMiddlewareв MIDDLEWARE_CLASSESнастройках?
alecxe

Добавьте {%csrf_token%}в форму в шаблоне.
Рохан

4
@ Рохан, он уже там, см. Вопрос.
alecxe

1
Ага, у меня уже есть CsrfViewMiddleware, и у меня уже есть csrf_token в моей форме

Я использовал модуль Django cors и обращался к нему через ReactJS. (Оба были на localhost). У меня тоже была эта проблема с OP. Я обнаружил, что добавление credentials: 'include'к запросу POST, а затем ТАКЖЕ добавление в django settings.py: CORS_ALLOW_CREDENTIALS = Trueпохоже, устранило проблему без необходимости добавления @csrf_exemptв представление. На самом деле это находится в документах ... pypi.org/project/django-cors-headers-multi * Я знаю, что это относится к одному из вопросов выше, но я пока не могу комментировать и хотел бы, надеюсь, сэкономить время кому-то еще. взял меня, чтобы найти t
DW

Ответы:


134

Это также может произойти, если CSRF_COOKIE_SECURE = Trueустановлено, и вы получаете доступ к сайту небезопасно, или если CSRF_COOKIE_HTTPONLY = Trueустановлено, как указано здесь и здесь


10
Благодаря! То же самое и для SESSION_COOKIE_SECURE = True.
NonameSL 02

74
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def your_view(request):
    if request.method == "POST":
        # do something
    return HttpResponse("Your response")

61
Полное отключение механизма безопасности - не лучший способ исправить ошибку.
Гийом Алжис

2
Если вы используете cookiecutter-django в 2017 году, это правильный ответ в производственной среде.
Андре Дуарте

1
Почему из любопытства?
Патрик Галлахер

3
Этот ответ не предлагает «полностью отключить механизм безопасности», он только говорит, как это сделать в одном случае, когда вы не сможете использовать токен CSRF. Это мой случай, когда мне нужно предложить внешнему клиенту действие POST.
mariotomo

Это элемент типа TODO, который я использую на этапе разработки, когда вы не можете предоставить токен csrf из пользовательского интерфейса. Но, конечно, не рекомендуется для живого приложения.
Аман Мадан

24

Если вы используете HTML5 Fetch API для выполнения запросов POST от имени зарегистрированного пользователя и получения Forbidden (CSRF cookie not set.), это может быть связано с тем, что по умолчанию fetchне включает файлы cookie сеанса, в результате чего Django думает, что вы другой пользователь, чем тот, кто загрузил страницу. .

Вы можете включить токен сеанса, передав параметр credentials: 'include'для получения:

var csrftoken = getCookie('csrftoken');
var headers = new Headers();
headers.append('X-CSRFToken', csrftoken);
fetch('/api/upload', {
    method: 'POST',
    body: payload,
    headers: headers,
    credentials: 'include'
})

Могу я узнать, что это за метод Header (), который вы создали? это глобальный метод javascript?
Abz Rockers 03

@AbzRockers: Да, Headersэто глобальный интерфейс javascript, часть HTML5 Fetch API. developer.mozilla.org/en-US/docs/Web/API/Headers
user85461

13

Исходя из этого, вы можете решить эту проблему, добавив декоратор sure_csrf_cookie в свое представление

from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def yourView(request):
 #...

если этот метод не работает. вы попытаетесь прокомментировать csrf в промежуточном программном обеспечении. и снова протестируем.


5

Я столкнулся с подобной ситуацией при работе с DRF, решение добавляло метод .as_view () к View в urls.py


Было бы лучше, если бы вы также включили какой-то код
Alex Jolig

1
@AlexJolig столкнулся с той же проблемой, проблема заключалась в том, что я забыл добавить .as_view()после себя мой ApiView. Вот как выглядел код: urlpatterns += path('resource', ResourceView)И вот как он должен понравиться: urlpatterns += path('resource', ResourceView.as_view())
Alveona

4

Если вы используете DRF, проверьте правильность ваших URL-шаблонов, возможно, вы забыли .as_view():

Вот как выглядел мой код:

urlpatterns += path('resource', ResourceView) 

И вот так должно быть:

urlpatterns += path('resource', ResourceView.as_view())

1

попробуйте проверить, установили ли вы в settings.py

 MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',)

В шаблоне данные форматируются с помощью csrf_token:

<form>{% csrf_token %}
</form>

У меня нет всего вашего кода, но я считаю, что дело здесь: def deposit (request, account_num): изменил его на def deposit (request): и найду способ обратного вызова account_num. теперь это будет зависеть от того, является ли account_num полем таблицы или переменной.
drabo2005

Это переменная {{account_num}}, но как это влияет на токен csrf?

Я считаю, что токен csrf относится только к запросу, поэтому он не может проверить или обработать, что происходит с переменной здесь. проверьте djangoproject.com, возможно, вы получите правильный ответ о csrf_token.
drabo2005

1

Эта проблема снова возникла недавно из-за ошибки в самом Python.

http://bugs.python.org/issue22931

https://code.djangoproject.com/ticket/24280

Среди затронутых версий были 2.7.8 и 2.7.9. Файл cookie не считывался правильно, если одно из значений содержало [символ.

Обновление Python (2.7.10) устраняет проблему.


1

Это также происходит, когда вы не устанавливаете действие формы.
Для меня эта ошибка показывалась, когда код был:

<form class="navbar-form form-inline my-2 my-lg-0" role="search" method="post">

Когда я исправил свой код так:

<form class="navbar-form form-inline my-2 my-lg-0" action="{% url 'someurl' %}" role="search" method="post">

моя ошибка исчезла.


0

Проблема заключается в том, что вы не обрабатываете GETзапросы должным образом или напрямую не публикуете данные, не получив предварительно форму.

Когда вы впервые заходите на страницу, клиент отправляет GETзапрос, в этом случае вы должны отправить html с соответствующей формой.

Позже пользователь заполняет форму и отправляет POST запрос с данными формы.

Ваше мнение должно быть таким:

def deposit(request,account_num):
   if request.method == 'POST':
      form_=AccountForm(request.POST or None, instance=account)
      if form.is_valid(): 
          #handle form data
          return HttpResponseRedirect("/history/" + account_num + "/")
      else:
         #handle when form not valid
    else:
       #handle when request is GET (or not POST)
       form_=AccountForm(instance=account)

    return render_to_response('history.html',
                          {'account_form': form},
                          context_instance=RequestContext(request))

0

Убедитесь, что для веб-сайтов установлены файлы cookie Chrome по умолчанию. Разрешить установку локальных данных (рекомендуется).


0

Способ 1:

from django.shortcuts import render_to_response
return render_to_response(
    'history.html',
    RequestContext(request, {
        'account_form': form,
    })

Способ 2:

from django.shortcuts import render
return render(request, 'history.html', {
    'account_form': form,
})

Поскольку метод render_to_response может иметь некоторые проблемы с ответными файлами cookie.


0

Я только что встречался один раз, решение - очистить куки. И может быть изменен при отладке, связанной с SECRET_KEY.


0

Очистка кеша моего браузера устранила эту проблему для меня. Я переключался между локальными средами разработки, чтобы выполнить руководство по django-blog-zinnia после работы над другим проектом, когда это произошло. Сначала я подумал, что это вызвало изменение порядка INSTALLED_APPS в соответствии с руководством, но я установил их обратно и не смог исправить это до очистки кеша.


0

Раньше я использовал Django 1.10, поэтому столкнулся с этой проблемой. Теперь я понизил его до Django 1.9, и он работает нормально.


Используя 1.10.3, у меня была эта проблема. Обновление до 1.10.6 исправило это для меня.
Майк Дарметко

0

У меня была такая же ошибка, в моем случае помогает добавление method_decorator:

from django.views.decorators.csrf import csrf_protect
from django.utils.decorators import method_decorator

method_decorator(csrf_protect)
def post(self, request):
    ...

0

Убедитесь, что серверная часть вашего сеанса django правильно настроена в settings.py. Тогда попробуйте это,

class CustomMiddleware(object):
  def process_request(self,request:HttpRequest):
      get_token(request)

Добавьте это промежуточное ПО settings.pyпод MIDDLEWARE_CLASSESили в MIDDLEWAREзависимости от версии django

get_token - возвращает токен CSRF, необходимый для формы POST. Маркер представляет собой буквенно-цифровое значение. Создается новый токен, если он еще не установлен.


-4

На ваш взгляд, вы используете декоратор csrf ??

from django.views.decorators.csrf import csrf_protect

@csrf_protect def view(request, params): ....

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.