Django + jQuery: why CSRF validation fails with multiple simultaneous queries

I came across the following situation (using Django1.4 and jQuery 1.7.1) that I would like to understand: I submit the form via the jQuery 'ajax' function, and until this request completes, I click on another element that submits the same form, but using jQuery 'submit' function. The answer I received is 403, the CSRF check failed. Now, of course, to prevent this error, it is enough to disable several simultaneous views (they work fine by themselves), but this does not help to understand where this particular error comes from.

Can anyone explain this? The csrf token is generated once per session, so it cannot be incompatible with csrf for the last request. Is this related to how jQuery queries are handled?

+4
source share
2 answers

The problem is resolved. I missed the fact that the js script responsible for calling ajax sets the attribute "disabled" to the form inputs (including the csrf token) in the beforeSend function - such disabled attrs are not sent to POST.

0
source

I think the problem is in your code. Just read the django code


Error in this block.

if not constant_time_compare(request_csrf_token, csrf_token): logger.warning('Forbidden (%s): %s', REASON_BAD_TOKEN, request.path, extra={ 'status_code': 403, 'request': request, } ) return self._reject(request, REASON_BAD_TOKEN) 

So, you, the script front end, send csrf_token which cookies (which send the browser) are not equal


Next code work

Tpl

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <a href="javascript:" class="req1">req1</a> <a href="javascript:" class="req2">req2</a> <br> <form id="foo" action="" method="POST">{% csrf_token %} {{ form.as_p }} <input type="submit"> </form> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ $('.req2').click(function(){ var form1 = $.post( '', $('#foo').serialize(), function(data){console.log(data)} ); }) $('.req1').click(function(){ var form1 = $.post( '', $('#foo').serialize(), function(data){console.log(data)} ); }) }) </script> </body> </html> 

View

 from django import forms from django.http import HttpResponse from django.shortcuts import render from django.views.decorators.csrf import csrf_protect class TestForm(forms.Form): test_field = forms.CharField() @csrf_protect def home(request): if request.method == 'POST': form = TestForm(request.POST) if form.is_valid(): return HttpResponse('all ok') else: form = TestForm() return render(request, 'page.html', { 'form': form, }, ) 
0
source

All Articles