问题
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
andCSRF_HEADER_NAME
in mysettings.py
;Explicitly setting
CSRF_COOKIE_SECURE = False
andCSRF_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