Django csrf_token is null in chrome
I have a slightly weird problem. I am writing a simple little application and I need to send some stuff back to django view. I am following the guide here: https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/ to set the ajax headers and have the following code in js:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// 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;
}
var csrftoken = getCookie('csrftoken');
console.log(csrftoken)
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
I have a form in my html with code:
<form onsubmit="return false;">
{% csrf_token %}
<input type="text" id="map-id-input"/>
<button id="map-id-btn" class='btn btn-default custom-btn'>
Go
</button>
</form>
I also have a piece of js code that runs when the button above is clicked:
$(function() {
$("#map-id-btn").click(function() {
checkMapID();
})
})
function checkMapID() {
var mapId = $("#map-id-input").val();
$.ajax({
url: "check_map_id/",
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: csrftoken,
map_id: mapId,
},
success: function(status_dict) {
if (status_dict.status === 1) {
$("#status").html("Valid map ID <br> Loading Data...")
window.location = status_dict.url;
}
else {
$("#status").html("Invalid map ID. Please try again, or contact ...")
}
},
error: function(result) {
console.log(result)
}
});
}
All my Javacript is in one file, placed at the top of my template.
The view that catches the URL 'check_map_id /' looks like this:
@ensure_csrf_cookie
def check_map_id(request):
map_id = request.POST['map_id']
if map_id not in GEOJSON_LOOKUP.keys():
status = json.dumps({
'status': 0,
'url': '',
})
return HttpResponse(status, content_type="application/json")
else:
status = json.dumps({
'status': 1,
'url': reverse('map', args=(map_id,)),
})
return HttpResponse(status, content_type="application/json")
Now when I run the application on my local machine using firefox, I get a valid csrf token that is printed to the console. If I run the application on my local machine in chrome or IE, I get zero typing. The same behavior is repeated on a real site. I am using linux (mint) and oddly enough if I run the app in firefox on a windows machine it returns null in firefox as well. Something strange here! Any ideas? I seem to be doing exactly what the django documentation suggests.
UPDATE: I added @ensure_csrf_cookie to my index and now I get the token printed on both browsers on my local machine. However, the code doesn't work on my real server. If I output some random console.logs in js, they are displayed on the real server, so the code runs. I'm really at a loss.
UPDATE2: So I established that the problem is that on my live site, the document.cookie property is not being set. I think the csrftoken = "..." cookie is set by django. It seems to be a setting on my local machine, but not on my site. The code is identical: /. What's going on here?!
source to share
Ok. I found the problem! It was a simple case where you weren't actually sending the csrf token to the html page. I focused on the ajax call, which was actually correct.
I changed the view, which actually rendered the page where the form was broken:
@ensure_csrf_cookie
def index(request):
context = RequestContext(request)
return render_to_response('vis_it_app/index.html', context)
The key here is "RequestContext" which by default also sends the csfr token. It was a mission ...
So, let's summarize. Make this work.
-
Make sure the csrf token is sent to the page you intend to use it using RequestContext and @ensure_csrf_cookie
-
Make sure {% csrf_token%} is somewhere in your form
-
Add the custom AJAX code found here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax to your JavaScript pages
-
Make sure the middleware token is sent back with the ajax data with:
$. Ajax ({url: "...", type: "POST", data type: "...", data: {csrfmiddlewaretoken: csrftoken, ...},
And that should do it.
source to share