2012-05-19 86 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