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
Use Firefox with Firebug. Open the 'Console' tab while firing the ajax request. With DEBUG=True
you get the nice django error page as response and you can even see the rendered html of the ajax response in the console tab.
Then you will know what the error is.
I have a solution. in my JS I have two functions. First to get Cookies (ie. csrftoken):
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
Second one is my ajax function. in this case it's for login and in fact doesn't return any thing, just pass values to set a session:
function LoginAjax() {
//get scrftoken:
const csrftoken = getCookie('csrftoken');
var req = new XMLHttpRequest();
var userName = document.getElementById("Login-Username");
var password = document.getElementById("Login-Password");
req.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
//read response loggedIn JSON show me if user logged in or not
var respond = JSON.parse(this.responseText);
alert(respond.loggedIn);
}
}
req.open("POST", "login", true);
//following header set scrftoken to resolve problem
req.setRequestHeader('X-CSRFToken', csrftoken);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send("UserName=" + userName.value + "&Password=" + password.value);
}
If you use the $.ajax
function, you can simply add the csrf
token in the data body:
$.ajax({
data: {
somedata: 'somedata',
moredata: 'moredata',
csrfmiddlewaretoken: '{{ csrf_token }}'
},
The {% csrf_token %}
put in html templates inside <form></form>
translates to something like:
<input type='hidden' name='csrfmiddlewaretoken' value='Sdgrw2HfynbFgPcZ5sjaoAI5zsMZ4wZR' />
so why not just grep it in your JS like this:
token = $("#change_password-form").find('input[name=csrfmiddlewaretoken]').val()
and then pass it e.g doing some POST, like:
$.post( "/panel/change_password/", {foo: bar, csrfmiddlewaretoken: token}, function(data){
console.log(data);
});
I've just encountered a bit different but similar situation. Not 100% sure if it'd be a resolution to your case, but I resolved the issue for Django 1.3 by setting a POST parameter 'csrfmiddlewaretoken' with the proper cookie value string which is usually returned within the form of your home HTML by Django's template system with '{% csrf_token %}' tag. I did not try on the older Django, just happened and resolved on Django1.3. My problem was that the first request submitted via Ajax from a form was successfully done but the second attempt from the exact same from failed, resulted in 403 state even though the header 'X-CSRFToken' is correctly placed with the CSRF token value as well as in the case of the first attempt. Hope this helps.
Regards,
Hiro
If someone is strugling with axios to make this work this helped me:
import axios from 'axios';
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
Source: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/