POST方法总是返回403禁止(POST method always return 403 Forb

2019-07-29 11:09发布

我已阅读Django的- CSRF验证失败和几个到Django和POST方法相关的问题(和答案)。 其中最好的,但并非工作换我的回答是https://stackoverflow.com/a/4707639/755319

所有经批准的答案建议至少三件事情:

  1. 使用的RequestContext作为render_to_response_call的第三个参数
  2. 添加{%csrf_token%}与POST方法各种形式
  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)

这是我的模板(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,而且从来没有发现这样的问题)?

Answer 1:

尝试把RequestContext的在search_form视图的选择render_to_response:

context_instance=RequestContext(request)


Answer 2:

我也许错了,但是我发现相当复杂的上述解决方案。

什么工作对我来说是简单的,包括我的CSRF令牌到我的职务的请求。

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


Answer 3:

为了避免此类问题的最简单方法是使用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})


Answer 4:

这个答案是,可能在未来会遇到同样的问题的人。

该CSRF {{csrf_token}}防止针对跨站点请求伪造模板所需的形式Django的标签。 CSRF它使已经访问过客户端的浏览器发出请求到自己的服务器恶意网站。 因此Django提供的csrf_token变得非常简单了你的Django服务器和站点打击这种类型的恶意攻击的保护。 如果您的形式不受csrf_token保护,Django的返回一个403页禁止。 这是为您的网站的一种保护,特别是当令牌不是故意冷落。

但是,在某些场景下一个Django网站不希望使用csrf_token来保护它的形式。 例如,我公司开发的USSD应用并且需要视图功能以接收来自所述USSD API POST请求。 我们应该注意到,POST请求不是从客户端,因此CSRF不可能的风险上的形式,因为一个恶意网站无法提交请求。 当用户当表单提交拨一个USSD代码,而不是在接收到POST请求。

换句话说,存在其中的功能将需要得到一个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')

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



Answer 5:

响应是403个bcoz,Django的要求在每一个岗位一个CSRF令牌(包括在后数据)要求你做。

有多种方法来做到这一点,例如:

从饼干获取单词和方法在文章中说明在此处输入链接的描述

要么

您可以从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);
  }
});


Answer 6:

您还可以使用

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

代替

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

因为direct_to_template增加RequestContext自动。 但是请注意, direct_to_template将被弃用,Django还提供了使用CBV TemplateView代替。

RequestContext允许您使用的上下文处理器。 这是你的错误: {% csrf_token %} outputed空字符串和你有403。



Answer 7:

您需要使用RequestContext根据您的回复

例如在view.py文件

from django.template import RequestContext

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


文章来源: POST method always return 403 Forbidden