2012-04-30 413 views
9

我嘗試構建一個可以將數據添加到sqlite3數據庫的非常簡單的網站。我有一個帶有兩個文本輸入的POST表單。CSRF驗證失敗。請求中止

的index.html:

{% if top_list %} 
    <ul> 
    <b><pre>Name Total steps</pre></b> 
    {% for t in top_list %} 
     <pre>{{t.name}} {{t.total_steps}}</pre> 
    {% endfor %} 
    </ul> 
    {% else %} 
    <p>No data available.</p> 
{% endif %} 
<br> 
<form action="/steps_count/" method="post"> 
    {% csrf_token %} 
    Name: <input type="text" name="Name" /><br /> 
    Steps: <input type="text" name="Steps" /><br /> 
    <input type="submit" value="Add" /> 
</form> 

forms.py:

from django import forms 
from steps_count.models import Top_List 

class Top_List_Form(forms.ModelForm): 
    class Meta: 
     model=Top_List 

views.py:

# Create your views here. 
from django.template import Context, loader 
from django.http import HttpResponse 
from steps_count.models import Top_List 
from steps_count.forms import Top_List_Form 
from django.template import RequestContext 
from django.shortcuts import get_object_or_404, render_to_response 

def index(request): 

if request.method == 'POST': 
    #form = Top_List_Form(request.POST) 
    print "Do something" 
else: 
    top_list = Top_List.objects.all().order_by('total_steps').reverse() 
    t = loader.get_template('steps_count/index.html') 
    c = Context({'top_list': top_list,}) 
    #output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list]) 
    return HttpResponse(t.render(c)) 

然而,當我點擊 「提交」 按鈕,我得到403錯誤:

CSRF verification failed. Request aborted. 

我已經包含在index.html的{% csrf_token %}。然而,如果它是一個RequestContext問題,我真的不知道在哪裏以及如何使用它。我希望一切都發生在同一頁面(index.html)。

回答

13

使用自動添加RequestContextrender shortcut

from django.http import HttpResponse 
from django.shortcuts import get_object_or_404, render 
from steps_count.models import Top_List 
from steps_count.forms import Top_List_Form 


def index(request): 

    if request.method == 'POST': 
     #form = Top_List_Form(request.POST) 
     return HttpResponse("Do something") # methods must return HttpResponse 
    else: 
     top_list = Top_List.objects.all().order_by('total_steps').reverse() 
     #output = ''.join([(t.name+'\t'+str(t.total_steps)+'\n') for t in top_list]) 
     return render(request,'steps_count/index.html',{'top_list': top_list}) 
+0

太感謝你了,它的工作原理! – Bebe

1

,您應該使用的

from django.shortcuts import render_to_response 
. 
. 
. 
return render_to_response("steps_count/index.html", {'top_list': top_list}, context_instance=RequestContext(request)) 

代替

return HttpResponse(t.render(c)) 

讀關於 「上下文處理器」,看看this鏈接瞭解CSRF保護Django是如何工作的詳細信息。

UPDATE

我誤讀了的HttpResponse選擇render_to_response作爲。我更新了我以前的答案。

1

這裏常見的錯誤是使用render_to_response(這在較老的教程中通常使用),它不會自動包含RequestContext。渲染會自動包含它。

在遵循教程創建新應用時學習了這一點,並且在新應用中CSRF不適用於頁面。

4

當您發現此類消息時,它表示CSRF令牌丟失或不正確。所以你有兩個選擇。

  1. 對於POST表單,您需要確保:

    • 您的瀏覽器是否接受Cookie。

    • 在模板中,每個POST表單中都有一個{%csrf_token%}模板標記,用於定位內部URL。

  2. 另一個簡單的方法是隻註釋一行(不推薦)( 'django.middleware.csrf.CsrfViewMiddleware')在從MIDDLEWARE_CLASSES設置標籤。

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware', 
        'django.middleware.common.CommonMiddleware', 
        # 'django.middleware.csrf.CsrfViewMiddleware', 
        'django.contrib.auth.middleware.AuthenticationMiddleware', 
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
        'django.contrib.messages.middleware.MessageMiddleware', 
        'django.middleware.clickjacking.XFrameOptionsMiddleware', 
    

+0

感謝您的第二部分。我根本不需要那個! :) – SaurabhJinturkar

+0

關閉CSRF不是*解決方案。請不要這樣做。 (答案的第2部分) – elnygren

0
function yourFunctionName(data_1,data_2){ 
     context = {} 
     context['id'] = data_1 
     context['Valid'] = data_2 
     $.ajax({ 
      beforeSend:function(xhr, settings) { 
        function getCookie(name) { 
          var cookieValue = null; 
          if (document.cookie && document.cookie != '') { 
           var cookies = document.cookie.split(';'); 
           for (var i = 0; i < cookies.length; i++) { 
            var cookie = jQuery.trim(cookies[i]); 
            if (cookie.substring(0, name.length + 1) == (name + '=')) { 
             cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
             break; 
            } 
           } 
          } 
          return cookieValue; 
         } 
         if (settings.url == "your-url") 
          xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 
        }, 

      url: "your-url", 
      type: "POST", 
      data: JSON.stringify(context), 
      dataType: 'json', 
      contentType: 'application/json' 
     }).done(function(data) { 
    }); 
+0

你應該這樣寫你的ajax。 –

0
if you put {%csrf_token%} and still you have the same issue, please try to change your angular version. because its works for me. initially i faced this issue while using angular 1.4.x version . after i degrade it into angular 1.2.8, my problem was fixed. 
and dont forgot to add angular-cookies.js and put this on your js file. 
if you using post request. 
"app.run(function($http, $cookies) { 
    console.log($cookies.csrftoken) 
    $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken; 
}); 
" 
0

在HTML報頭,添加

<meta name="csrf_token" content="{{ csrf_token }}"> 
在JS

接着/角配置:

app.config(function($httpProvider){ 
    $httpProvider.defaults.headers.post['X-CSRFToken'] = $('meta[name=csrf_token]').attr('content'); 
} 
1

你可能已經錯過了加入以下到您的窗體:

{% csrf_token %} 
相關問題