18

Djangoを読みました-CSRF検証が失敗し、djangoとPOSTメソッドに関連するいくつかの質問(および回答)があります。最高の答えの1つは、https://stackoverflow.com/a/4707639/755319です。

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

  1. render_to_response_callの3番目のパラメーターとしてRequestContextを使用します
  2. POSTメソッドを使用してすべてのフォームに{%csrf_token%}を追加します
  3. settings.pyでMIDDLEWARE_CLASSESを確認してください

提案どおりに実行しましたが、エラーが発生しました。私はdjango1.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から来ており、これまでにそのような問題を見つけたことはありません)。
4

8 に答える 8

17

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

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

$.ajax({
    type: "POST",
    url: "/reports/",
    data: { csrfmiddlewaretoken: "{{ csrf_token }}",   // < here 
            state:"inactive" 
          },
    success: function() {
        alert("pocohuntus")
        console.log("prototype")
    }
})
于 2013-06-28T01:50:44.877 に答える
11

この答えは、将来この同じ問題に遭遇する可能性のある人々のためのものです。

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

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

于 2018-01-13T01:48:33.780 に答える
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})
于 2012-05-19T09:44:20.480 に答える
3

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

context_instance=RequestContext(request)
于 2012-05-19T08:08:30.240 に答える
2

応答は403bcozです。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);
  }
});
于 2016-06-19T15:29:11.430 に答える
1

RequestContextあなたはあなたの応答で使用する必要があります

たとえばview.pyファイルで

from django.template import RequestContext

def home(request):
    return render_to_response('home.html',RequestContext(request, {}))
于 2015-06-03T10:04:31.927 に答える
0

使用することもできます

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はTemplateView代わりにCBVを使用することを提案していることに注意してください。

RequestContextコンテキストプロセッサを使用できます。そして、これはあなたの間違いです:{% csrf_token %}空の文字列を出力し、あなたは403を得ました。

于 2012-05-19T08:45:03.290 に答える
0

これは私のためにそれを解決しました。Djangoのドキュメントに記載されているように、RESTAPIに対してPOSTメソッドを直接作成する前に実行する必要のある処理がいくつかあります。コードは次のとおりです。

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

const csrftoken = getCookie('csrftoken');
console.log(csrftoken)





$.ajax({
    method:'POST',
    url:"//127.0.0.1:8000/app/homepage/", /*change it to your api endpoint*/
    headers: {'X-CSRFToken': csrftoken},
    data : { "data" : "3"}
    
   
})

このソリューションで保証できないことの1つは、セキュリティの側面です。

于 2021-03-27T18:57:10.563 に答える