I could use some help complying with Django\'s CSRF protection mechanism via my AJAX post. I\'ve followed the directions here:
http://docs.djangoproject.com/en/dev/r
It seems nobody has mentioned how to do this in pure JS using the X-CSRFToken
header and {{ csrf_token }}
, so here's a simple solution where you don't need to search through the cookies or the DOM:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url, true);
xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
xhttp.send();
1) the django csrf check (assuming you're sending one) is here
2) In my case, settings.CSRF_HEADER_NAME
was set to 'HTTP_X_CSRFTOKEN' and my AJAX call was sending a header named 'HTTP_X_CSRF_TOKEN' so stuff wasn't working. I could either change it in the AJAX call, or django setting.
3) If you opt to change it server-side, find your install location of django and throw a breakpoint in the csrf middleware
.f you're using virtualenv
, it'll be something like: ~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
import ipdb; ipdb.set_trace() # breakpoint!!
if request_csrf_token == "":
# Fall back to X-CSRFToken, to make things easier for AJAX,
# and possible for PUT/DELETE.
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
Then, make sure the csrf
token is correctly sourced from request.META
4) If you need to change your header, etc - change that variable in your settings file
Using Django 3.1.1 and all solutions I tried failed. However, adding the "csrfmiddlewaretoken" key to my POST body worked. Here's the call I made:
$.post(url, {
csrfmiddlewaretoken: window.CSRF_TOKEN,
method: "POST",
data: JSON.stringify(data),
dataType: 'JSON',
});
And in the HTML template:
<script type="text/javascript">
window.CSRF_TOKEN = "{{ csrf_token }}";
</script>
The issue is because django is expecting the value from the cookie to be passed back as part of the form data. The code from the previous answer is getting javascript to hunt out the cookie value and put it into the form data. Thats a lovely way of doing it from a technical point of view, but it does look a bit verbose.
In the past, I have done it more simply by getting the javascript to put the token value into the post data.
If you use {% csrf_token %} in your template, you will get a hidden form field emitted that carries the value. But, if you use {{ csrf_token }} you will just get the bare value of the token, so you can use this in javascript like this....
csrf_token = "{{ csrf_token }}";
Then you can include that, with the required key name in the hash you then submit as the data to the ajax call.
Non-jquery answer:
var csrfcookie = function() {
var cookieValue = null,
name = 'csrftoken';
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
};
usage:
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.setRequestHeader('X-CSRFToken', csrfcookie());
request.onload = callback;
request.send(data);
As it is not stated anywhere in the current answers, the fastest solution if you are not embedding js into your template is:
Put <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
before your reference to script.js file in your template, then add csrfmiddlewaretoken
into your data
dictionary in your js file:
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})