Файл 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.