Django の組み込み CSRF (クロスサイト リクエスト フォージェリ) 保護は、django-admin startproject
でプロジェクトを作成するときにデフォルトで有効になり、CSRF トークンを利用して悪意のあるリクエストから保護します。 このミドルウェアは settings.py
.
Django アプリケーションへのすべての POST リクエストには有効な CSRF トークンが必要です。 Django テンプレートでは、POST メソッドを使用してフォーム内に {% csrf_token %}
を含めることでこれを実現します。 ただし、個別のフロントエンド AJAX リクエストで CSRF 保護を処理するには、別のアプローチが必要です。
このチュートリアルでは、別のフロントエンドからの AJAX リクエストを使用して単純な Django アプリケーションを保護する方法を示します。
このサンプル アプリケーションには 2 つのエンドポイントがあります:
/get-picture
: サーバーに保存されている画像の URL を取得します。/set-picture
: サーバーに保存されている画像の URL を更新します。わかりやすくするために、エラー処理は省略しています。 初期のバックエンド コード (urls.py
内) は次のとおりです:
<code class="language-python">from django.urls import path from django.http import JsonResponse import json picture_url = "https://picsum.photos/id/247/720/405" def get_picture(request): return JsonResponse({"picture_url": picture_url}) def set_picture(request): if request.method == "POST": global picture_url picture_url = json.loads(request.body)["picture_url"] return JsonResponse({"picture_url": picture_url}) urlpatterns = [ path("get-picture", get_picture), path("set-picture", set_picture) ]</code>
対応するフロントエンド関数 (簡略化):
<code class="language-javascript">// GET request to retrieve the image URL async function get_picture() { const res = await fetch("http://localhost:8000/get-picture"); const data = await res.json(); return data.picture_url; } // POST request to update the image URL async function set_picture(picture_url) { const res = await fetch("http://localhost:8000/set-picture", { method: "POST", body: JSON.stringify({ "picture_url": picture_url }) }); }</code>
Cross-Origin Resource Sharing (CORS) を処理するには、django-cors-headers
パッケージを使用します。
django-cors-headers
をインストールします:
<code class="language-bash">pip install django-cors-headers</code>
settings.py
を設定します:
<code class="language-python">INSTALLED_APPS = [ "corsheaders", # ... other apps ] MIDDLEWARE = [ "corsheaders.middleware.CorsMiddleware", # ... other middleware ] CORS_ALLOWED_ORIGINS = ["http://localhost:4040"] # Adjust port as needed CSRF_TRUSTED_ORIGINS = ["http://localhost:4040"] # Add your frontend origin</code>
GET リクエストは正しく機能するようになりましたが、CSRF 保護により POST リクエストは失敗します。 これを解決するには、CSRF トークンを手動で管理する必要があります。
CSRF トークンを提供する新しいビューを作成します:
<code class="language-python">from django.views.decorators.csrf import ensure_csrf_cookie from django.http import JsonResponse @ensure_csrf_cookie def get_csrf_token(request): return JsonResponse({"success": True}) urlpatterns = [ # ... other paths path("get-csrf-token", get_csrf_token), ]</code>
フロントエンドを更新してトークンを取得します (js-cookie
を使用):
<code class="language-javascript">fetch("http://localhost:8000/get-csrf-token", { credentials: "include" });</code>
credentials: "include"
オプションは、ブラウザが Set-Cookie
ヘッダーを処理し、csrftoken
Cookie を保存することを保証します。 ブラウザの開発者ツールのネットワーク タブを調べて、Cookie が設定されていることを確認します。
最後に、ヘッダーに CSRF トークンを含めるように set_picture
関数を変更します。
<code class="language-javascript">async function set_picture(picture_url) { const res = await fetch("http://localhost:8000/set-picture", { method: "POST", credentials: "include", headers: { 'X-CSRFToken': Cookies.get("csrftoken") }, body: JSON.stringify({ "picture_url": picture_url }) }); }</code>
これにより、X-CSRFToken
Cookie の値を含む csrftoken
ヘッダーが追加され、POST リクエストの成功が可能になります。
このアプローチには、特にフロントエンドとバックエンドを異なるドメインにデプロイする場合に制限があります。 ブラウザのセキュリティ ポリシーにより、サードパーティ Cookie の設定またはアクセスが妨げられ、CSRF トークンの管理に影響を与える可能性があります。
以上がDjango および AJAX リクエストでの CSRF 保護の使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。