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 Link to heading
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 Link to heading
Form Link to heading
<form>
{% csrf_token %}
</form>
Single AJAX request Link to heading
$.ajax({
data: {
csrfmiddlewaretoken: '{{ csrf_token }}'
},
Multiple AJAX request Link to heading
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);
}
}
});