Skip to main content

CSRF in Django

·2 mins

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:

  1. When user login for the first time, Django generate a csrf_secret, add random salt and encrypt it as A, save A to cookie csrftoken.
  2. When Django processing tag {{ csrf_token }} or {% csrf_token %}, it read csrftoken cookie A, reverse it to csrf_secret, add random salt and encrypt it as B, return corresponding HTML.
  3. When Django receive POST request, it will retrive cookie csrftoken as A, and tries to get csrfmiddlewaretoken value B from POST data, if it does not exist, it will get header X-CSRFToken value as B. Then A and B will be reversed to csrf_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);
        }
    }
});

Ref #

  1. Cross Site Request Forgery protection
  2. csrf.py
  3. What’s the relationship between csrfmiddlewaretoken and csrftoken?