web-dev-qa-db-ja.com

POSTメソッドは常に403 Forbiddenを返します

私は Django-CSRF検証失敗 およびDjangoおよびPOSTメソッドに関連するいくつかの質問(および回答))を読みました。 best-but-not-working-for-meの答えは https://stackoverflow.com/a/4707639/755319

承認された回答はすべて、少なくとも3つのことを示唆しています。

  1. Render_to_response_callの3番目のパラメーターとしてRequestContextを使用する
  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)

これは私のテンプレートです(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 forbiddenエラーがまだあり、CSRF検証が失敗したことを通知しています。

2つの質問があります。

  1. このエラーを修正する方法は?
  2. Djangoで「POST」を作成するのが難しいのはなぜですか、つまり、これを冗長にする特定の理由があるということです(私はPHPから来ており、以前にそのような問題を発見したことがありません)?
13
goFrendiAsgard

RequestContextをsearch_formビューのrender_to_responseに配置してみてください。

context_instance=RequestContext(request)
3
zubinmehta

私は間違っているかもしれませんが、上記の解決策はかなり複雑だと思いました。

私にとってうまくいったのは、単に私のcsrfトークンを私の投稿リクエストに含めることでした。

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

このような問題を回避する最も簡単な方法は、 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})
5
Burhan Khalid

この回答は、将来同じ問題が発生する可能性のある人を対象としています。

Djangoのフォームに必要なCSRF {{csrf_token}}テンプレートタグは、クロスサイトリクエストフォージェリを防止します。CSRFにより、クライアントのブラウザがアクセスした悪意のあるサイトがDjangoによって提供されるcsrf_tokenは、Djangoサーバーとサイトがこのタイプの悪意のある攻撃から保護されることを簡単にします。あなたのフォームはcsrf_tokenで保護されていません、Djangoは403禁止ページを返します。これは、特にトークンが意図的に省略されていない場合のWebサイトの保護のフォームです。

しかし、Djangoサイトがcsrf_tokenを使用してフォームを保護したくない場合があります。たとえば、USSDアプリケーションを開発し、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')

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

3
Iyanuoluwa Ajao

応答は403 bcozです。Djangoは、すべてのPOSTリクエストでcsrfトークン(投稿データに含まれる)を必要とします)。

これを行うには、次のようなさまざまな方法があります。

クッキーからトークンを取得する方法は、記事で説明されています ここにリンクの説明を入力してください

または

テンプレートで利用可能な{{csrf_token}}を使用してDOMからアクセスできます

したがって、2番目の方法を使用します。

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);
  }
});
2
Hiro

あなたも使うことができます

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 %}空の文字列を出力し、403を取得しました。

0
San4ez

応答にはRequestContextを使用する必要があります

たとえばview.pyファイル

from Django.template import RequestContext

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