2012-07-18 46 views
4

我遇到了以下我想要了解的情况(使用Django1.4和jQuery 1.7.1): 我通过jQuery'ajax'函数,并在这个请求完成之前,我点击另一个提交相同的表单,但使用jQuery的“提交”功能的元素。我得到的回应 - 403,CSRF验证失败。当然,为了防止这种错误,只需禁用多个同时提交(它们自己可以正常工作)就足够了,但这无助于理解具体错误的来源。Django + jQuery:为什么在多个同时发生的请求中CSRF验证失败

任何人都可以解释这一点吗?每个会话都会生成一次csrf标记,因此后一个请求不会出现某种csrf不匹配的情况。 这是否与jQuery handels请求的方式有关?

+0

如果你自己做,而不是与ajax提交并发的jQuery的“提交”作品? – Anentropic 2012-07-23 16:22:44

+0

是你的ajax [正确](https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax)发送POST。并且你能提供确切的错误信息,因为在源文件中我没有看到你的错误'REASON_NO_REFERER =“引用者检查失败 - 没有引用者。” REASON_BAD_REFERER =“引荐者检查失败 - %s与%s不匹配。” REASON_NO_CSRF_COOKIE =“未设置CSRF cookie”。 REASON_BAD_TOKEN =“CSRF令牌丢失或不正确。” – nk9 2012-07-23 19:33:47

+0

@Antropic:是的,提交工作时单独完成。 – fjern 2012-07-25 15:36:26

回答

0

问题解决了 - 我错过了负责ajax调用的js脚本在beforeSend函数中的表单输入(包括csrf标记)上设置'disabled'属性的事实 - 这些禁用的attrs不是在POST中发送的。

0

我觉得你的代码存在问题。只读django代码


在此块中捕获错误。

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) 

所以你前端脚本发送csrf_token这和饼干(其发送的浏览器)是不相等的


下一个代码工作

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> 

视图

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, 
      }, 
    ) 
相关问题