2011-03-31 96 views
6

根據django文檔,對於1.3中的ajax post請求(至少在jquery中),我們只需要將這snippet添加到主js文件。這段代碼從cookie中獲取csrftoken,然後爲所有ajax請求設置它。這是工作,但如果cookie中不存在csrftoken呢?我認爲render_to_response和render都會自動檢查會話中是否有csrftoken,如果token不存在,就爲我們設置它。但他們不是。那麼,我需要自己來執行它?或者也許有另一種方法來處理Ajax csrf保護?Django 1.3中的Ajax CSRF問題

回答

3

你的cookie將只包含CSRF令牌,如果有一個模板標籤{% csrf_token %}在模板中使用生成請求,或者如果你調用get_token(與request對象作爲參數)從django.middleware.csrf

get_token函數設置request對象上的元信息,該對象又會通知django.middleware.csrf.CsrfViewMiddleware中間件設置cookie。

3

對於Ajax,您應該在每次請求時都傳遞csrf標記。 jQuery的,我用下面的代碼:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
    if(!options.crossDomain) { 
     if(options.data) { 
      options.data += "&"; 
     } else { 
      options.data = ""; 
     } 
     options.data += "csrfmiddlewaretoken={{csrf_token}}"; 
    } 
}); 
11

當有一個已使用{%csrf_token%}在頁面上沒有形成,該cookie不會被髮送。因此,正如您所指出的那樣,當您嘗試在這樣的頁面上使用Ajax時會出現錯誤。這會導致不穩定的行爲,如果你有一個網站混合形式和ajax職位的各種組合的網站。

這已上報並固定:https://code.djangoproject.com/ticket/15354

在補丁的解決方案,將要推出與1.3.1,是ensure_cookie_csrf裝飾。該裝飾器不存在於1.3或1.2.5中

然而,不需要等待。只是這行添加到其中包含AJAX職位CSRF形式的任何觀點:

request.META["CSRF_COOKIE_USED"] = True 

例子:

def calculator(request): 
    request.META["CSRF_COOKIE_USED"] = True 
    return render_to_response('calc.html', {'form': CalcForm()}) 

僅供參考 - 這是裝飾究竟是幹什麼的。

+0

根據[CSRF Django文檔](https:// docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views。decorators.csrf.ensure_csrf_cookie),ensure_cookie_csrf修飾器是Django 1.4的新增功能。 – 2012-05-14 16:33:15

+1

是的,ensure_csrf_cookie裝飾器在Django 1.4中着陸。很遺憾,不在1.3.1中 – bjunix 2012-05-22 12:41:26

1

我發現解決這個問題的一種方法是使用預先存在的表單作爲AJAX數據的起始點。

<form id="ajax_form" stye="display: none;">{% csrf_token %}</form> 

然後你就可以通過JQuery的序列化功能,在你的JavaScript使用:

var data = $('#ajax_form').serialize(); 
data += "&mydata=69"; 

你甚至可以使用隱藏的表單中的隱藏字段,這樣你就不必使用字符串連接到內置你的POST數據。

1

如果您使用的是@csrf_protect修飾器,請確保包含表單的視圖和數據被髮布爲使用修飾器的視圖。

我有類似的問題。我只有@csrf_protect在發佈視圖工作正常在本地測試,但是當我去現場o得到了403驗證失敗的問題添加裝飾器他頁面視圖固定此