2012-04-30 346 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 %} 
相关问题