0

Hi so here's the problem: I'm doing a login through ajax without page reloading - just click Login button giving your username and password and a request with two cookies, sessionid and csrftoken, is coming. Note that page has NOT been reloaded. Right after I am triggering another ajax (POST) request which requires logged in user:

 @login_required                                                                                             
 @ajax                                                                                                       
 def member_index(request):
   ....

I get a 403 Forbidden error which comes from CsrfMiddleware (because if I turn it off in settings, everything works). The question is what I am doing wrong? If I reload the page, the ajax request works. I have sniffed the cookies in the browser (sessionid and csrftoken) and it looks everything is set good. ]

Henrik Andersson
  • 45,354
  • 16
  • 98
  • 92
friko
  • 567
  • 2
  • 7
  • 20
  • You need to include the value of the csrftoken in your POST. – Joseph Sep 15 '15 at 18:47
  • I have checked this post request from the chrome browser: the csrftoken is set. And I wrote that the after page refreshing the request is working properly, so I am setting in javaScript the csrfToken. I think the problem is somewhere else. But thank you for quick response. – friko Sep 15 '15 at 18:52

2 Answers2

0

You need to add csrftoken to your ajax call, you can do that using this code given in this answer (Django CSRF check failing with an Ajax POST request)

$.ajaxSetup({ 
     beforeSend: function(xhr, settings) {
         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;
         }
         if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
             // Only send the token to relative URLs i.e. locally.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         }
     } 
});
Community
  • 1
  • 1
levi
  • 22,001
  • 7
  • 73
  • 74
  • I am already doing it. If I would not, then my second request would not work. I have checked the network tab in google chrome where I can notice the response and request. The csrfToken is set by the ajax call. – friko Sep 15 '15 at 19:03
0

Solved. Thank you all for helping. I had to add this handler:

$( document ).ajaxSend(function( event, xhr, settings ) {
    if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') {
        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;
        }
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            // Only send the token to relative URLs i.e. locally.
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});

It is updating the "X-CSRFToken" field each time an ajax has to be send. The ajaxSetup sets up only on the first time during page reload. Then any incomming ajax request with new csrftoken has to update the "X-CSRFToken" field.

friko
  • 567
  • 2
  • 7
  • 20