POST方法总是返回403 Forbidden

goF*_*ard 13 django post csrf django-csrf

我读过Django - CSRF验证失败,以及与django和POST方法相关的几个问题(和答案).其中一个最好但不能正常工作的答案是/sf/answers/329534761/

所有批准的答案都表明至少有三件事:

  1. 使用RequestContext作为render_to_response_call的第三个参数
  2. 使用POST方法在每个表单中添加{%csrf_token%}
  3. 检查settings.py中的MIDDLEWARE_CLASSES

我完全按照建议做了,但错误仍然出现.我使用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)
Run Code Online (Sandbox Code Playgroud)

这是我的模板(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 %}
Run Code Online (Sandbox Code Playgroud)

我重新启动了服务器,但403禁止错误仍然存​​在,告诉CSRF验证失败.

我有两个问题:

  1. 如何解决这个错误?
  2. 为什么在django中制作"POST"这么难,我的意思是有任何特定的理由让它变得如此冗长(我来自PHP,以前从未发现过这样的问题)?

lay*_*cat 11

我可能错了,但我发现上述解决方案相当复杂.

对我有用的只是将我的csrf令牌包含在我的帖子请求中.

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


Iya*_*jao 10

这个答案是为将来可能会遇到同样问题的人准备的。

{{csrf_token}}Django 中表单所需的 CSRF模板标签可防止跨站点请求伪造。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。此装饰器将视图标记为不受中间件确保的保护。

from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')
Run Code Online (Sandbox Code Playgroud)

Django 还提供了另一个装饰器,与 执行相同的功能{{csrf_token}},但它不会拒绝传入的请求。这个装饰器是@requires_csrf_token. 例如:

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

本文中将提到的最后一个装饰器与 {{csrf_token}} 完全相同,它被称为@csrf_protect. 但是,单独使用此装饰器并不是最佳实践,因为您可能会忘记将其添加到您的视图中。例如:

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

下面是一些可以更好地指导和解释的链接。

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


Bur*_*lid 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})
Run Code Online (Sandbox Code Playgroud)


zub*_*hta 3

尝试将 RequestContext 放入 search_form 视图的 render_to_response 中:

context_instance=RequestContext(request)
Run Code Online (Sandbox Code Playgroud)

  • 因为必须在您的视图中创建“csrf_token”,以便 django 可以将其传递给模板。在您的情况下,由于您的搜索视图不创建令牌,因此模板中的“{% csrf_token %}”为“空字符串(无)”,结果页面验证失败 (3认同)
  • https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-to-use-it - 阅读第 3 点 (2认同)