---
title: "Django の CSRF 保護を利用する"
version: 6.0
locale: ja
source: https://docs.djangoproject.com/ja/6.0/howto/csrf/
canonical: https://djangodocs.dev/ja/6.0/howto/csrf/
---
# Django の CSRF 保護を利用する

CSRF 対策をあなたのビューで有効にするには、以下の手順に従ってください:

1. CSRF ミドルウェアは、デフォルトで [`MIDDLEWARE`](/ja/6.0/ref/settings/#std-setting-MIDDLEWARE) 設定で有効になっています。もし設定をオーバーライドするときは、`'django.middleware.csrf.CsrfViewMiddleware'` が、 CSRF 攻撃への対策がされていることを前提とした他の全てのビュー・ミドルウェアの前に来るようにしてください。

   (推奨されませんが) もし対策を無効にする場合は、[`csrf_protect()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect) を使って特定のビューを保護することができます (下記を参照してください)。
2. POST フォームを使う全てのテンプレートで、POST が内部 URL に使われる場合は、`<form>` 要素の内部で [`csrf_token`](/ja/6.0/ref/templates/builtins/#std-templatetag-csrf_token) タグを使用してください。

   ```html+django
   <form method="post">{% csrf_token %}
   ```

   この方法は、外部の URL を対象にする POST フォームで使ってはいけません。CSRF トークンが外部に漏れ、脆弱性の原因となります。
3. 対応するビュー関数では、`{% csrf_token %}` が正しく機能するように、レスポンスをレンダリングする際に [`RequestContext`](/ja/6.0/ref/templates/api/#django.template.RequestContext) が使用されていることを確認してください。 [`render()`](/ja/6.0/topics/http/shortcuts/#django.shortcuts.render) 関数、ジェネリックビュー、または contrib アプリを使用している場合は、これらはすべて `RequestContext` を使用しているため、すでに対応しています。

## AJAXでCSRF保護を利用する

上記の方法は AJAX の POST でも利用可能ですが、多少不便です。すべての POST リクエストで、CSRF トークンを POST するデータに忘れずに含めなければなりません。そのため、別の方法が用意されており、各 XMLHttpRequest に対して、`X-CSRFToken` という独自ヘッダーに CSRF トークンの値を設定することができます ([`CSRF_HEADER_NAME`](/ja/6.0/ref/settings/#std-setting-CSRF_HEADER_NAME) 設定でヘッダー名が指定できます)。多くの JavaScript のフレームワークはすべてのリクエストについて、指定したヘッダーを設定するようなフック機能を提供しているので、普通は簡単に設定できます。

まず、CSRFトークンを取得する必要があります。これは、[`CSRF_USE_SESSIONS`](/ja/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS) と [`CSRF_COOKIE_HTTPONLY`](/ja/6.0/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY) の設定が有効になっているかどうかによって異なります。

### [`CSRF_USE_SESSIONS`](/ja/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS) と [`CSRF_COOKIE_HTTPONLY`](/ja/6.0/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY) が `False` に設定されている場合にトークンを取得する

トークン取得のソースとして推奨されるのは `csrftoken` クッキーです。これは、上記で概説したようにビューに対する CSRF 保護を有効化した場合にセットされます。

デフォルトでは、CSRF トークンの cookie は `csrftoken` という名前ですが、[`CSRF_COOKIE_NAME`](/ja/6.0/ref/settings/#std-setting-CSRF_COOKIE_NAME) の設定を通じて変更することができます。

以下のようにしてトークンを取得できます:

```javascript
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');
```

上記のコードは [JavaScript Cookie library](https://github.com/js-cookie/js-cookie/) を使って `getCookie` を置き換えればシンプルにできます:

```javascript
const csrftoken = Cookies.get('csrftoken');
```

> **Note**
>
> CSRF トークンはマスクされた形で DOM にも存在しますが、これはテンプレート内で [`csrf_token`](/ja/6.0/ref/templates/builtins/#std-templatetag-csrf_token) を使って明示的にインクルードされたときだけです。クッキーはマスクされていない正規のトークンを含んでいます。 [`CsrfViewMiddleware`](/ja/6.0/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware) はどちらも受け付けます。しかし、 [BREACH](https://www.breachattack.com/) 攻撃から守るためには、マスクされたトークンを使うことを推奨します。

> **Warning**
>
> ビューが [`csrf_token`](/ja/6.0/ref/templates/builtins/#std-templatetag-csrf_token) テンプレートタグを含むテンプレートをレンダリングしていない場合、Django は CSRF トークンクッキーをセットしない可能性があります。フォームがページに動的に追加される場合がその典型です。このケースに対応するため、Django はクッキーを強制的にセットするビューのデコレータを提供しています: [`ensure_csrf_cookie()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie)。

### [`CSRF_USE_SESSIONS`](/ja/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS) または [`CSRF_COOKIE_HTTPONLY`](/ja/6.0/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY) が `True` の時トークンを取得する

[`CSRF_USE_SESSIONS`](/ja/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS) または [`CSRF_COOKIE_HTTPONLY`](/ja/6.0/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY) を有効にした場合、HTML に CSRF トークンを含め、JavaScript で DOM からトークンを読み取る必要があります:

```html+django
{% csrf_token %}
<script>
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
</script>
```

### AJAX 通信でトークンを設定する

最後に、AJAXリクエストにヘッダーを追加する必要があります。 [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/fetch) APIを使用してください:

```javascript
const request = new Request(
    /* URL */,
    {
        method: 'POST',
        headers: {'X-CSRFToken': csrftoken},
        mode: 'same-origin' // Do not send CSRF token to another domain.
    }
);
fetch(request).then(function(response) {
    // ...
});
```

## Jinja2テンプレートでCSRF保護を利用する

Django の [`Jinja2`](/ja/6.0/topics/templates/#django.template.backends.jinja2.Jinja2) テンプレートバックエンドは、すべてのテンプレートのコンテキストに `{{ csrf_input }}` を追加します。これは、Django テンプレート言語内の `{% csrf_token %}` と同じ意味です。例えば:

```html+jinja
<form method="post">{{ csrf_input }}
```

## デコレータメソッドの利用

全体を保護するために `CsrfViewMiddleware` を追加する代わりに、保護を必要とする特定のビューにおいて、まったく同じ機能を持つ [`csrf_protect()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect) デコレータを使えます。アウトプット内に CSRF トークンを挿入するビューと、POST フォームデータを受け入れるビューの両方で使用する必要があります (多くの場合同じビュー関数ですが、そうでない場合もあります)。

デコレータ自体で使うことは **非推奨** です。もし使い忘れた場合、セキュリティホールを抱えることになるからです。二重対策として両方を使うのは構いませんが、わずかにオーバーヘッドが増加します。

## リクエスト拒否に対処する

デフォルトでは、受信リクエストが `CsrfViewMiddleware` によって実行されるチェックに失敗した場合、ユーザーには "403 Forbidden" レスポンスが送信されます。これは通常、実際の CSRF が発生した場合、またはプログラミングエラーにより POST フォームに CSRF トークンが含まれていない場合にのみ送信されるべきです。

エラーページはとてもユーザーフレンドリーではないので、独自のビューを提供したいと考えるかもしれません。[`CSRF_FAILURE_VIEW`](/ja/6.0/ref/settings/#std-setting-CSRF_FAILURE_VIEW) の設定で実現できます。

CSRF の認証失敗は、 [django.security.csrf](/ja/6.0/ref/logging/#django-security-logger) ロガーに警告として記録されます。

## キャッシュによるCSRF保護を利用する

[`csrf_token`](/ja/6.0/ref/templates/builtins/#std-templatetag-csrf_token) テンプレートタグがテンプレートで使用されている場合(または `get_token` 関数が他の方法で呼び出されている場合)、`CsrfViewMiddleware` はレスポンスにクッキーと `Vary: Cookie` ヘッダをレスポンスに追加します。これは、`UpdateCacheMiddleware` が指示通りに使用された場合、このミドルウェアがキャッシュミドルウェアと協調的に動作することを意味します（ `UpdateCacheMiddleware` は他のすべてのミドルウェアよりも優先されます）。

しかし、個々のビューでキャッシュデコレータを使用すると、CSRF ミドルウェアはまだ Vary ヘッダや CSRF クッキーを設定できておらず、レスポンスはどちらも設定されずにキャッシュされます。この場合、CSRF トークンを挿入する必要があるビューでは、 [`django.views.decorators.csrf.csrf_protect()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect) デコレータを最初に使うべきです:

```
from django.views.decorators.cache import cache_page
from django.views.decorators.csrf import csrf_protect

@cache_page(60 * 15)
@csrf_protect
def my_view(request): ...
```

クラスベースのビューを使っている場合は、[Decorating class-based views](/ja/6.0/topics/class-based-views/intro/#id1) を参照してください。

## テストと CSRF 保護

通常、 `CsrfViewMiddleware` はビュー関数をテストする際に大きな障害となります。なぜなら、 POST リクエストごとに CSRF トークンを送信する必要があるからです。このため、Django のテスト用 HTTP クライアントは、ミドルウェアと `csrf_protect` デコレータを緩和するフラグをリクエストに設定するように変更されました。それ以外の点 (例えばクッキーの送信など) では同じように動作します。

何らかの理由でテストクライアントに CSRF チェックを実行して *ほしい* ときには、CSRF チェックの実行を強制するテストクライアントのインスタンスを作ることができます:

```pycon
>>> from django.test import Client
>>> csrf_client = Client(enforce_csrf_checks=True)
```

## エッジケース

ビューによっては、ここで想定している通常のパターンに当てはまらないような特殊な要求がある場合があります。このような状況では、多くのユーティリティが役に立ちます。それらが必要とされる可能性のあるシナリオについては、次のセクションで説明します。

### 特定のビューで CSRF 保護を無効化する

ほとんどのビューでCSRF保護が必要だが、わずかのビューでは必要でないケースがあります。

解決策: ミドルウェアを無効にして、必要なビュー全てに `csrf_protect` を適用するのではなく、ミドルウェアを有効にして [`csrf_exempt()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_exempt) を使ってください。

### `CsrfViewMiddleware.process_view()` が使われない場合のトークン設定

ビューが実行される前に `CsrfViewMiddleware.process_view` が実行されない場合があります（例えば、404ハンドラーや500ハンドラー）その場合でもフォームでCSRFトークンが必要となる場合。

解決策: [`requires_csrf_token()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.requires_csrf_token) を使用する

### 保護されていないビューにCSRFトークンを含める

`csrf_exempt` によって除外され、保護されていないビューがあるかもしれない中で、CSRFトークンを含めなければならないこともあります。

解決策: [`csrf_exempt()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_exempt) の後に続けて [`requires_csrf_token()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.requires_csrf_token) を使用してください (つまり、 `requires_csrf_token` が最も内側のデコレータとなるようにしてください)。

### 1つのパスに対してのみビューを保護する

ビューが CSRF 保護を必要とするのは、ある条件のときだけで、それ以外のときは CSRF 保護をしてはいけないときがあります。

解決方法: ビュー関数全体には [`csrf_exempt()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_exempt) を使用し、その中で保護が必要なパスに対して [`csrf_protect()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect) を使用します。例えば:

```
from django.views.decorators.csrf import csrf_exempt, csrf_protect

@csrf_exempt
def my_view(request):
    @csrf_protect
    def protected_path(request):
        do_something()

    if some_condition():
        return protected_path(request)
    else:
        do_something_else()
```

### HTML フォームなしで AJAX を使用するページの保護

AJAX 経由で POST リクエストを行うページにおいて、必要な CSRF クッキーを送信する [`csrf_token`](/ja/6.0/ref/templates/builtins/#std-templatetag-csrf_token) を持つ HTML フォームがないことがあります。

解決策: ページを送信するビューで [`ensure_csrf_cookie()`](/ja/6.0/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) を使います。

## 再利用可能なアプリケーションにおける CSRF 保護

開発者は `CsrfViewMiddleware` を個別にオフにすることができるので、CSRF に対するアプリケーションのセキュリティを保証するために、contrib アプリケーションの関連するビューには、すべて `csrf_protect` デコレータを適用しています。その他の再利用可能なアプリの開発者も、同様にセキュリティを保証したいのであれば、ビューに `csrf_protect` デコレータを適用してください。
