CSRF in Django
Table of Contents
CSRF(Cross-site request forgery) is a way to generate fake user request to target website. For example, on a malicious website A, there is a button, click it will send request to www.B.com/logout. When the user click this button, he will logout from website B unconsciously. Logout is not a big problem, but malicious website can generate more dangerous request like money transfer.
Django CSRF protection #
Each web framework has different approach to do CSRF protection. In Django, the validation process is below:
- When user login for the first time, Django generate a
csrf_secret
, add random salt and encrypt it as A, save A to cookiecsrftoken
. - When Django processing tag
{{ csrf_token }}
or{% csrf_token %}
, it readcsrftoken
cookie A, reverse it tocsrf_secret
, add random salt and encrypt it as B, return corresponding HTML. - When Django receive POST request, it will retrive cookie
csrftoken
as A, and tries to getcsrfmiddlewaretoken
value B from POST data, if it does not exist, it will get headerX-CSRFToken
value as B. Then A and B will be reversed tocsrf_secret
. If the values are identical, the validation is passed. Otherwise, a 403 error will raise.
Django CSRF Usage #
Form #
<form>
{% csrf_token %}
</form>
Single AJAX request #
$.ajax({
data: {
csrfmiddlewaretoken: '{{ csrf_token }}'
},
Multiple AJAX request #
Extracting csrftoken
from cookie and add it to header for each ajax
request.
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');
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);
}
}
});