0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Djangoで「CSRF検証に失敗したため、リクエストは中断されました。」が発生する

0
Posted at

事象

本番環境(VPS / Nginx / Dockerなど)でDjangoアプリケーションをHTTPS化して公開したところ、ログイン画面や管理画面、フォーム送信(POSTリクエスト)時に次の403エラー画面が表示された。

403 Forbidden
アクセス禁止 (403)
CSRF検証に失敗したため、リクエストは中断されました。

ALLOWED_HOSTS にドメインを設定しており、GETリクエストによるページ表示やHTTPSアクセス自体は問題なく行えているにもかかわらず、POST送信時のみエラーが発生する。

環境

  • Python 3.x
  • Django 4.0以降(Django 4.0でCSRFの仕様変更あり)
  • Nginx(リバースプロキシ)
  • Docker / Docker Compose
  • HTTPS(独自ドメイン)

原因

主な原因は、settings.pyCSRF_TRUSTED_ORIGINS にHTTPSのオリジンが登録されていないことである。

なぜ発生するのか

  1. Django 4.0以降の仕様変更
    Django 4.0以降、HTTPS環境下でのCSRF検証において、リクエストの Origin ヘッダー(または Referer ヘッダー)が CSRF_TRUSTED_ORIGINS に登録されているかを厳格に検証するようになった。

  2. ALLOWED_HOSTSCSRF_TRUSTED_ORIGINS の混同

    • ALLOWED_HOSTS: リクエストの Host ヘッダーを検証する設定。スキーム(https://)や末尾のスラッシュは含めない(例: example.com)。
    • CSRF_TRUSTED_ORIGINS: CSRF検証で信頼する送信元を指定する設定。スキーム(https://http://)を含める必要がある(例: https://example.com)。

ALLOWED_HOSTS だけを設定して CSRF_TRUSTED_ORIGINS を設定していない場合、GETアクセスは通るがPOST送信時のCSRF検証で弾かれてしまう。

対策

1. settings.pyCSRF_TRUSTED_ORIGINS を追加する

settings.py を開き、公開しているドメインのオリジン(スキーム付き)を追加する。

# settings.py

# Hostヘッダーの許可(スキームなし)
ALLOWED_HOSTS = [
    "example.com",
    "www.example.com",
]

# CSRFの信頼済みオリジン(スキームあり・末尾スラッシュなし)
CSRF_TRUSTED_ORIGINS = [
    "https://example.com",
    "https://www.example.com",
]

サブドメインを含めてまとめて許可したい場合は、次のようにワイルドカード指定も可能。

CSRF_TRUSTED_ORIGINS = [
    "https://*.example.com",
]

2. Nginxのリバースプロキシ設定を確認する

リバースプロキシ(Nginx)経由でリクエストを渡している場合、HTTPS通信であることをDjango側に正しく伝えるヘッダーが抜けていないか確認する。

# nginx.conf (または sites-available/*.conf)

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;  # これが必要
}

Nginxの設定を変更した場合はリロードする。

sudo nginx -t && sudo systemctl reload nginx

3. Djangoアプリケーション(Dockerコンテナ)を再起動する

settings.py の変更を反映させるため、Djangoのプロセス(またはDockerコンテナ)を再起動する。

# Docker Composeの場合
docker compose restart web

※ NginxのリロードだけではDjango側の設定変更は反映されないため注意。

4. 動作確認

ブラウザからログイン画面やフォームを開き、POST送信を行ってエラーが出ずに処理が完了することを確認する。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?