2012-05-19 245 views
11

我已閱讀Django - CSRF verification failed以及與django和POST方法有關的幾個問題(和答案)。其中最好的,但並非工作換我的答案是https://stackoverflow.com/a/4707639/755319POST方法總是返回403 Forbidden

所有經批准的答案建議至少三件事情:

  1. 使用的RequestContext作爲render_to_response_call
  2. 添加的第三個參數{%csrf_token%}與POST方法
  3. 各種形式的檢查MIDDLEWARE_CLASSES settings.py中

我究竟做的建議,但錯誤依然出現了。我使用Django 1.3.1(Ubuntu的,從12.04庫)和Python 2.7(默認從Ubuntu的)

這是我的看法:

# Create your views here. 
from django.template import RequestContext 
from django.http import HttpResponse 
from django.shortcuts import render_to_response 
from models import BookModel 

def index(request): 
    return HttpResponse('Welcome to the library') 

def search_form(request): 
    return render_to_response('library/search_form.html') 

def search(request): 
    if request.method=='POST': 
     if 'q' in request.POST: 
      q=request.POST['q'] 
      bookModel = BookModel.objects.filter(title__icontains=q) 
      result = {'books' : bookModel,} 
      return render_to_response('library/search.html', result, context_instance=RequestContext(request)) 
     else: 
      return search_form(request) 
    else: 
     return search_form(request) 

,這是我的模板(search_form.html):

{% extends "base.html" %} 
{% block content %} 
<form action="/library/search/" method="post"> 
    {% csrf_token %} 
    <input type="text" name="q"> 
    <input type="submit" value="Search"> 
</form> 
{% endblock %} 

我已重新啓動服務器,但403禁止的錯誤仍然存​​在,告訴CSRF驗證失敗。

我有2個問題:

  1. 如何解決這個問題?
  2. 爲什麼在django中做一個「POST」很困難,我的意思是說有什麼特別的理由讓它變得如此冗長(我來自PHP,之前從未發現過這樣的問題)?

回答

3

嘗試把RequestContext的在search_form視圖的選擇render_to_response:

context_instance=RequestContext(request) 
+0

那的作品,謝謝您的回答。 但是如何以及爲什麼?你能解釋一下嗎? – goFrendiAsgard

+2

https://docs.djangoproject.com/zh/dev/ref/contrib/csrf/#how-to-use-it - 閱讀要點#3 – zubinmehta

+2

由於'csrf_token'必須在您的視圖中創建,因此django可以通過它的模板。在你的情況下,由於你的搜索視圖不會創建一個標記,所以你的模板中的'{%csrf_token%}'是'空字符串(None)'並且結果頁驗證失敗 – FallenAngel

0

您還可以使用

direct_to_template(request, 'library/search.html', result) 

代替

render_to_response('library/search.html', result, context_instance=RequestContext(request)) 

因爲direct_to_template增加RequestContext AUT omatically。但請注意,direct_to_template將被棄用,django提供使用CBV TemplateView

RequestContext允許您使用上下文處理器。這是你的錯誤:{% csrf_token %}輸出空字符串,你得到了403.

+0

嗨,謝謝你的評論,似乎我應該考慮很多東西,然後才熟悉django:D – goFrendiAsgard

5

避免這種問題的最簡單方法是使用render快捷方式。

from django.shortcuts import render 
# .. your other imports 

def search_form(request): 
    return render(request, 'library/search_form.html') 

def search(request): 
    q = request.GET.get('q') 
    results = BookModel.objects.all() 
    if q: 
     results = results.filter(title__icontains=q) 
    return render(request, 'library/search.html', {'result': results}) 
+0

+1對於'django.me' – San4ez

+0

必須儘快嘗試,似乎很清楚,謝謝你的回答。有沒有使用這種方法的缺點? 我不知道爲什麼是文檔和djangobook提供這樣一個詳細的語法,如果有這樣一個明確的語法 – goFrendiAsgard

+0

我知道這是一箇舊線程,但我更新它來進一步澄清搜索方法。希望這現在(更多)有用。 –

9

我也許錯了,但我發現上述解決方案相當複雜。

對我而言,只需將我的csrf標記添加到我的發佈請求中即可。

$.ajax({ 
    type: "POST", 
    url: "/reports/", 
    data: { csrfmiddlewaretoken: "{{ csrf_token }}", // < here 
      state:"inactive" 
      }, 
    success: function() { 
     alert("pocohuntus") 
     console.log("prototype") 
    } 
}) 
+2

爲我工作 - 謝謝! – skaz

0

您需要使用RequestContext根據您的回覆

例如 在view.py文件

from django.template import RequestContext 

def home(request): 
    return render_to_response('home.html',RequestContext(request, {})) 
2

的響應403個bcoz, Django的需要CSRF令牌(包括在後數據)在你做的每一個POST請求中。

有各種不同的方式來做到這一點,如:

獲取從餅乾和方法的標記已經在文章中說明enter link description here

您可以從DOM使用訪問{{ csrf_token}},模板提供

所以現在使用第二種方法:

var post_data = { 
    ... 
    'csrfmiddlewaretoken':"{{ csrf_token }}" 
    ... 
} 
$.ajax({ 
    url:'url', 
    type:'POST' 
    data:post_data, 
    success:function(data){ 
    console.log(data); 
    }, 
    error:function(error){ 
    console.log(error); 
    } 
}); 
1

這個答案適用於未來可能會遇到同樣問題的人。

CSRF {{csrf_token}} Django中表單所需的模板標記可防止跨站點請求僞造。 CSRF使得客戶瀏覽器訪問的惡意網站可以向自己的服務器發出請求。因此,由django提供的csrf_token可以讓你的django服務器和站點受到保護以防止這種類型的惡意攻擊。如果你的表單沒有被csrf_token保護,django返回一個403禁止頁面。這是對您的網站的一種保護形式,尤其是在令牌未被故意遺漏的情況下。

但有些情況下,django網站不希望使用csrf_token保護其表單。例如,我開發了一個USSD應用程序,並且需要一個視圖函數來接收來自USSD API的POST請求。我們應該注意到,POST請求不是來自客戶端的表單,因此CSRF的風險是不可能的,因爲惡意網站無法提交請求。 POST請求在用戶撥打USSD代碼時收到,而不是在提交表單時收到。

換句話說,有些情況下函數需要獲取POST請求,並且不需要{{csrf_token}}。

Django爲我們提供了一個裝飾器@csrf_exempt。這個裝飾器標誌着一個視圖被免除了中間件保證的保護。

​​

Django的還提供了執行與{{csrf_token}}相同功能的另一裝飾,但它不拒絕傳入請求。這個裝飾工作人員是@requires_csrf_token。例如:

@requires_csrf_token 
def my_view(request): 
    c = {} 
    # ... 
    return render(request, "a_template.html", c) 

將在這篇文章提到的最後裝飾不完全一樣的東西作爲{{csrf_token}},它被稱爲@csrf_protect。然而,使用這個裝飾器本身並不是最佳實踐,因爲您可能忘記將它添加到視圖中。例如:

@csrf_protect 
def my_view(request): 
    c = {} 
    # ... 
    return render(request, "a_template.html", c) 

下面是一些可以更好地指導和解釋的鏈接。

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#module-django.views.decorators.csrf

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/

http://www.squarefree.com/securitytips/web-developers.html#CSRF