2012-07-18 41 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, 
      }, 
    ) 
相關問題