"CSRF token missing or incorrect" while post parameter via AJAX in Django

brsbilgic picture brsbilgic · Jun 28, 2011 · Viewed 90.6k times · Source

I try to post parameter like

 jQuery.ajax(
        {
            'type': 'POST',
            'url': url,
            'contentType': 'application/json',
            'data': "{content:'xxx'}",
            'dataType': 'json',
            'success': rateReviewResult 
        }
    );

However, Django return Forbidden 403. CSRF verification failed. Request aborted. I am using 'django.middleware.csrf.CsrfViewMiddleware' and couldn't find how I can prevent this problem without compromising security.

Answer

sigurd picture sigurd · Jun 30, 2011

You can make AJAX post request in two different ways:

  1. To tell your view not to check the csrf token. This can be done by using decorator @csrf_exempt, like this:

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def your_view_name(request):
        ...
    
  2. To embed a csrf token in each AJAX request, for jQuery it may be:

    $(function () {
        $.ajaxSetup({
            headers: { "X-CSRFToken": getCookie("csrftoken") }
        });
    });
    

    Where the getCookie function retrieves csrf token from cookies. I use the following implementation:

    function getCookie(c_name)
    {
        if (document.cookie.length > 0)
        {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1)
            {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start,c_end));
            }
        }
        return "";
     }
    

    Also, jQuery has a plugin for accessing cookies, something like that:

    // set cookie
    $.cookie('cookiename', 'cookievalue');
    // read cookie
    var myCookie = $.cookie('cookiename');
    // delete cookie
    $.cookie('cookiename', null);