Django 1.9 AJAX form CSRF token 403 error - “CSRF cookie not set”

末鹿安然 提交于 2019-11-29 14:29:13

问题


I've seen a lot about this on SO, but nothing can fix my problem.

Problem:

With CSRF middleware enabled, Django responds with 403 on AJAX form request, stating:

"CSRF cookie not set."

Following the documentation, a JS functionality was implemented, that sets custom "X-CSRFToken" header.

It works as expected, gets "csrftoken" cookie from browser and posts it along with AJAX request:

x-csrftoken: 1a0u7GCQG0wepZHQNThIXeYpMy2lZOf2

But response is still 403.

Tried solutions:

I've tried everything I could find on SO or web, specifically:

  • Checking that middleware is enabled:

    MIDDLEWARE_CLASSES = [
        ...
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        ...
    ]
    
  • Different browsers with cookies enabled;

  • Decorating my view with @ensure_csrf_cookie;

  • Setting {% csrf_token %} in my template;

  • Using render shortcut which takes right request context;

  • Setting custom CSRF_COOKIE_NAME and CSRF_HEADER_NAME in my settings.py;

  • Explicitly setting CSRF_COOKIE_SECURE = False and CSRF_COOKIE_HTTPONLY = False;

  • Explicitly setting CSRF_TRUSTED_ORIGINS setting;

  • Testing on development and production server;

  • Even request.META["CSRF_COOKIE_USED"] = True in my view, as someone suggested.

And still got nothing.

Headers:

If I use @csrf_exempt and print(request.META) in my view, it's clear that custom header "X-CSRFToken" is present in request and formatted according to Django documentation, with "HTTP_" prefix, replaced hyphens with underscores, all uppercase: "HTTP_X_CSRFTOKEN".

Even more, it's value matches with cookie set by Django.

Cookies:

Strange thing is, if I try to print(request.COOKIES) in my view, on page and form load I can see "csrftoken" cookie there, but dictionary is empty on AJAX request. Can it be the problem?

Desperate to find what is actually wrong. Thank you for reading this.


回答1:


Ok, the issue is quite simple then:

Fetch API is not sending credentials by default. According to MDN:

The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests. This is similar to XHR’s withCredentials flag, but with three available values.

Default is omit, and it never sends cookies. You just need to add same-origin to your fetch() function arguments:

fetch(formUrl, {
    ...
    credentials: 'same-origin',
    ...
})

And you'll be good to go : )



来源:https://stackoverflow.com/questions/35868312/django-1-9-ajax-form-csrf-token-403-error-csrf-cookie-not-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!