---
title: "Djangoにおけるパスワード管理"
version: 6.0
locale: ja
source: https://docs.djangoproject.com/ja/6.0/topics/auth/passwords/
canonical: https://djangodocs.dev/ja/6.0/topics/auth/passwords/
---
# Djangoにおけるパスワード管理

パスワード管理は一般的に、不必要に再発明されるべきではないものです。Djangoはユーザーのパスワードを管理するための安全で柔軟なツールセットを提供するよう努めています。このドキュメントでは、Djangoがパスワードを保存する方法、ストレージハッシュの設定方法、およびハッシュされたパスワードを扱ういくつかのユーティリティについて説明します。

> **See also**
>
> ユーザーが強力なパスワードを使ったとしても、攻撃者が通信経路上において盗聴をおこなう可能性があります。パスワード (または他の機密データ) がプレーンな HTTP コネクションで送信されないように、 [HTTPS](/ja/6.0/topics/security/#security-recommendation-ssl) を使用してください。なぜなら、HTTP はパスワードスニッフィングに対して脆弱であるからです。

## Djangoのパスワード保存方法

DjangoはデフォルトでPBKDF2を利用した、柔軟なパスワード保存システムを提供します。

[`User`](/ja/6.0/ref/contrib/auth/#django.contrib.auth.models.User) オブジェクトの [`password`](/ja/6.0/ref/contrib/auth/#django.contrib.auth.models.User.password) 属性は、次のような形式の文字列です。

```text
<algorithm>$<iterations>$<salt>$<hash>
```

Those are the components used for storing a User's password, separated by the
dollar-sign character and consist of: the hashing algorithm, the number of
algorithm iterations (work factor), the random salt, and the resulting password
hash. The algorithm is one of a number of one-way hashing or password storage
algorithms Django can use; see below. Iterations describe the number of times
the algorithm is run over the hash. Salt is the random seed used and the hash
is the result of the one-way function.

デフォルトでは、Djangoは [NIST](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf) が推奨するパスワードストレッチングメカニズムである [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) アルゴリズムと SHA256 ハッシュを使用します。これはほとんどのユーザーに十分有効なはずです。非常に安全で、クラックするのに膨大な計算時間を必要とします。

However, depending on your requirements, you may choose a different
algorithm, or even use a custom algorithm to match your specific
security situation. Again, most users shouldn't need to do this -- if
you're not sure, you probably don't. If you do, please read on:

Django は [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) 設定を参照して、使用するアルゴリズムを選択します。これは、この Django インストールがサポートしているハッシュアルゴリズムクラスのリストです。

パスワードの保存には、 Django は [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) の最初のハッシャーを使います。別のアルゴリズムで新しいパスワードを保存するには、 [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) にあなたの好きなアルゴリズムを最初に書いてください。

パスワードの検証のために、 Django は保存されたパスワードのアルゴリズム名と一致するハッ シャーをリストの中から探します。保存されたパスワードが [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) にないアルゴリズ ム名を持つ場合、それを検証しようとすると `ValueError` が発生します。

デフォルトでの [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS)

```
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    "django.contrib.auth.hashers.ScryptPasswordHasher",
]
```

これは、Djangoは [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) を使用して全てのパスワードを保存しますが、PBKDF2SHA1、 [argon2](https://en.wikipedia.org/wiki/Argon2) 、および [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) で保存されたパスワードのチェックもサポートすることを意味しています。

次のいくつかのセクションでは、高度なユーザーがこの設定を変更するための一般的な方法について説明します。

### Django で Argon2 を使う

[Argon2](https://en.wikipedia.org/wiki/Argon2) は、次世代ハッシュアルゴリズムを選定するコミュニティ主催のオープンコンペティションである、2015年の [Password Hashing Competition](https://www.password-hashing.net/) の優勝者です。カスタムハードウェアで計算しても、通常のCPUで計算するよりも有利にならないように設計されています。Argon2パスワードハッシュのデフォルトのバリアントはArgon2idです。

[Argon2](https://en.wikipedia.org/wiki/Argon2) はサードパーティのライブラリを必要とするため、 Django のデフォルトではありません。しかし、 Password Hashing Competition パネルでは、 Django がサポートしている他のアルゴリズムではなく、 Argon2 をすぐに使うことを推奨しています。

Argon2idをデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:

1. [argon2-cffi](https://pypi.org/project/argon2-cffi/) パッケージをインストールしてください。 `python -m pip install django[argon2]` コマンドでインストールできます。このコマンドは、`python -m pip install argon2-cffi` と同等ですが、Djangoの `pyproject.toml` に記載されているバージョン要件が考慮されます。
2. [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) を変更して、`Argon2PasswordHasher` を最初にリストアップします。つまり、設定ファイルに下記のように書きます:

   ```
   PASSWORD_HASHERS = [
       "django.contrib.auth.hashers.Argon2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
       "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
       "django.contrib.auth.hashers.ScryptPasswordHasher",
   ]
   ```

   Django に [パスワードのアップグレード](#password-upgrades) をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。

### Django で `bcrypt` を使う

[Bcrypt](https://en.wikipedia.org/wiki/Bcrypt) は一般的なパスワード保存アルゴリズムで、特にパスワードの長期保存用に設計されています。サードパーティのライブラリを使う必要があるため、 Django がデフォルトで使うものではありませんが、多くの人が使いたいでしょうから、 Django は最小限の労力で bcrypt をサポートしています。

Bcrypt をデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:

1. [bcrypt](https://pypi.org/project/bcrypt/) パッケージをインストールしてください。 `python -m pip install django[bcrypt]` コマンドでインストールできます。このコマンドは、`python -m pip install bcrypt` と同等ですが、Djangoの `pyproject.toml` に記載されているバージョン要件が考慮されます。
2. [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) を変更して、`BCryptSHA256PasswordHasher` を最初にリストアップします。つまり、設定ファイルに下記のように書きます:

   ```
   PASSWORD_HASHERS = [
       "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
       "django.contrib.auth.hashers.Argon2PasswordHasher",
       "django.contrib.auth.hashers.ScryptPasswordHasher",
   ]
   ```

   Django に [パスワードのアップグレード](#password-upgrades) をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。

これで Django はデフォルトのストレージアルゴリズムとして Bcrypt を使うようになります。

### Django で `scrypt` を使う

[scrypt](https://en.wikipedia.org/wiki/Scrypt) は、ブルートフォース攻撃を減速させるために設定されたイテレーション数を利用するという点で、PBKDF2やbcryptと似ています。しかし、PBKDF2とbcryptは多くのメモリを必要としないため、十分なリソースを持つ攻撃者は、攻撃プロセスを高速化するために大規模な並列攻撃を仕掛けることができます。 [scrypt](https://en.wikipedia.org/wiki/Scrypt) は、攻撃者が使用できる並列処理の量を制限するために、他のパスワードベースの鍵導出関数と比較してより多くのメモリを使用するように特別に設計されています。

[scrypt](https://en.wikipedia.org/wiki/Scrypt) をデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:

1. [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) を変更して、`ScryptPasswordHasher` を最初にリストアップします。つまり、設定ファイルに下記のように書きます:

   ```
   PASSWORD_HASHERS = [
       "django.contrib.auth.hashers.ScryptPasswordHasher",
       "django.contrib.auth.hashers.PBKDF2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
       "django.contrib.auth.hashers.Argon2PasswordHasher",
       "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
   ]
   ```

   Django に [パスワードのアップグレード](#password-upgrades) をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。

> **Note**
>
> `scrypt` はOpenSSL 1.1+を必要とします。

### ソルトのエントロピーを増加させる

ほとんどのパスワードハッシュはレインボーテーブル攻撃から守るために、パスワードハッシュと一緒にソルトを含んでいます。ソルトはランダムな値であり、レインボーテーブルのサイズとコストを増加させます。現在は `BasePasswordHasher` の `salt_entropy` 値で128ビットに設定されています。計算機やストレージのコストが下がれば、この値を上げる必要があります。独自のパスワードハッシュを実装する場合、パスワードハッシュに希望するエントロピーレベルを使用するために、この値を自由に上書きできます。 `salt_entropy` の単位はビットです。

> **実装の詳細**
>
> ソルト値が保存されるメカニズムにより、 `salt_entropy` 値は実際には最小値です。たとえば、128という値は実際には131ビットのエントロピーを含むソルトを提供します。

### work factor を増やす

#### PBKDF2 と bcrypt

PBKDF2 と bcrypt アルゴリズムは、ハッシュ化に何度もイテレート（ラウンド）します。これは意図的に攻撃者の速度を低下させ、ハッシュ化されたパスワードに対する攻撃を困難にします。しかし、計算能力が上がるにつれて、イテレーションの回数を増やす必要があります。私たちは妥当なデフォルト値を選びました（そして Django のリリー スごとに増やす予定です）が、セキュリティの必要性や利用可能な処理能力に応じて、上げたり下げたりすることもできます。そのためには、適切なアルゴリズムをサブクラス化し、 `iterations` パラメータをオーバーライドします (bcrypt hasher をサブクラス化するときは `rounds` パラメータを使います)。たとえば、デフォルトの PBKDF2 アルゴリズムで使用するイテレーションの回数を増やすには、次のようにします:

1. `django.contrib.auth.hashers.PBKDF2PasswordHasher` のサブクラスを作成します:

   ```
   from django.contrib.auth.hashers import PBKDF2PasswordHasher

   class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
       """
       A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.
       """

       iterations = PBKDF2PasswordHasher.iterations * 100
   ```

   これをプロジェクトのどこかに保存します。たとえば、 `myproject/hashers.py` のようなファイルに保存します。
2. 新しいハッシャーを [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) の最初のエントリーとして追加します:

   ```
   PASSWORD_HASHERS = [
       "myproject.hashers.MyPBKDF2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2PasswordHasher",
       "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
       "django.contrib.auth.hashers.Argon2PasswordHasher",
       "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
       "django.contrib.auth.hashers.ScryptPasswordHasher",
   ]
   ```

これで Django が PBKDF2 を使ってパスワードを保存する際に、より多くのイテレーションを使うようになります。

> **Note**
>
> bcrypt の `rounds` は対数の work factor で、たとえば 12 ラウンドは `2 ** 12` のイテレーションを意味します。

#### Argon2

Argon2には、カスタマイズ可能な以下の属性があります:

1. `time_cost` はハッシュ内のイテレートする回数をコントロールします。
2. `memory_cost` は、ハッシュの計算に必要なメモリのサイズをコントロールします。
3. `parallelism` はハッシュの計算をいくつのCPUで並列化できるかを制御します。

これらの属性のデフォルト値は、おそらく問題ないでしょう。パスワード・ハッシュが速すぎたり遅すぎたりすると判断した場合は、以下のように微調整できます:

1. `parallelism` は、ハッシュを計算するスレッド数を指定します。
2. `memory_cost` には、余裕を持ったメモリのKiBを選択してください。
3. `time_cost` を調整し、パスワードのハッシュにかかる時間を測定します。 `time_cost` は、あなたにとって許容できる時間を選んでください。もし `time_cost` に 1 を指定しても許容できないほど遅い場合は、 `memory_cost` を下げてください。

> **memory_cost の解釈**
>
> argon2 コマンドラインユーティリティと他のいくつかのライブラリは、 `memory_cost` パラメータを Django が使う値とは異なる解釈をします。変換は `memory_cost == 2 ** memory_cost_commandline` で行います。

#### `scrypt`

[scrypt](https://en.wikipedia.org/wiki/Scrypt) にはカスタマイズ可能な以下の属性があります:

1. `work_factor` controls the number of iterations within the hash and the
   size of memory for computation (*N*). It must be a power of 2.
2. `block_size` controls the internal block size (*r*), tuning the algorithm
   to memory latency.
3. `parallelism` controls how many independent computations may run in
   parallel (*p*).
4. `maxmem` はハッシュの計算中に使用できるメモリの最大サイズを制限します。デフォルトは `0` で、OpenSSL ライブラリによるデフォルトの制限を意味します。

We've chosen reasonable defaults, but you may wish to tune it up or down,
depending on your security needs and available processing power and memory.

> **メモリ使用量の見積もり**
>
> [scrypt](https://en.wikipedia.org/wiki/Scrypt) に必要な最小のメモリサイズは以下の通りです:
>
> ```
> work_factor * 2 * block_size * 64
> ```
>
> そのため、 `work_factor` や `block_size` の値を変更する際には `maxmem` を調整する必要があるかもしれません。
>
> If the underlying implementation of [scrypt](https://en.wikipedia.org/wiki/Scrypt) is fully multithreaded, the
> memory requirement is multiplied by the `parallelism` value.

### パスワードのアップグレード

ユーザーがログインする際、もしそのパスワードが推奨されるアルゴリズム以外で保存されていた場合、Djangoは自動で推奨されるアルゴリズムへ更新します。つまり、Djangoの古いインストールでも、ユーザーのログイン時に自動的にセキュリティが強化され、新しい（より良い）保存アルゴリズムが開発されるたびに切り替えることができるということです。

ただし、Djangoは  [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) で定義されたアルゴリズムを使用するパスワードしか更新できません。そのため、新しいシステムにアップグレードする際には絶対にこのリストからエントリを「削除」しないでください。そうしないと、定義されてないアルゴリズムを使用するユーザーのパスワードを更新できなくなります。ハッシュされたパスワードは、PBKDF2のイテレーション回数、bcrypt のラウンド数、または argon2 の属性数を増やす (または減らす) と更新されます。

データベース上の全てのパスワードがデフォルトのハッシュアルゴリズムでエンコードされていない場合、デフォルト以外のアルゴリズムでエンコードされたパスワードを持つユーザーと、存在しないユーザー（デフォルトのハッシュアルゴリズムが実行されます）に対するログインリクエストにかかる時間の差に起因する、ユーザー列挙型タイミング攻撃に対して脆弱になる可能性があることに注意してください。 [古いパスワードハッシュの更新](#wrapping-password-hashers) によりこれを軽減できます。

### ログインを必要としないパスワードアップグレード

既存のデータベースが MD5 のような古くて弱いハッシュを使用している場合、ユーザがログインしたときにハッシュのアップグレードが行われるのを待つのではなく、自分でハッシュをアップグレードしたいと思うかもしれません (ユーザがサイトに戻ってこない場合は、アップグレードが行われないかもしれません)。この場合、「ラップ」パスワードハッシュを使用できます。

この例では、PBKDF2(MD5(password)) を使用するように MD5 ハッシュのコレクションをマイグレーションし、ユーザがログイン時に正しいパスワードを入力したかどうかをチェックするために、対応するパスワードハッシュを追加します。組み込みの `User` モデルを使用しており、プロジェクトには `accounts` アプリがあると仮定します。このパターンをカスタマイズすることで、任意のアルゴリズムやカスタムユーザモデルで動作させることができます。

まず、独自のハッシャーを追加します:

*`accounts/hashers.py`*

```python
from django.contrib.auth.hashers import (
    PBKDF2PasswordHasher,
    MD5PasswordHasher,
)

class PBKDF2WrappedMD5PasswordHasher(PBKDF2PasswordHasher):
    algorithm = "pbkdf2_wrapped_md5"

    def encode_md5_hash(self, md5_hash, salt, iterations=None):
        return super().encode(md5_hash, salt, iterations)

    def encode(self, password, salt, iterations=None):
        _, _, md5_hash = MD5PasswordHasher().encode(password, salt).split("$", 2)
        return self.encode_md5_hash(md5_hash, salt, iterations)
```

データマイグレーションは次のようになります:

*`accounts/migrations/0002_migrate_md5_passwords.py`*

```python
from django.db import migrations

from ..hashers import PBKDF2WrappedMD5PasswordHasher

def forwards_func(apps, schema_editor):
    User = apps.get_model("auth", "User")
    users = User.objects.filter(password__startswith="md5$")
    hasher = PBKDF2WrappedMD5PasswordHasher()
    for user in users:
        algorithm, salt, md5_hash = user.password.split("$", 2)
        user.password = hasher.encode_md5_hash(md5_hash, salt)
        user.save(update_fields=["password"])

class Migration(migrations.Migration):
    dependencies = [
        ("accounts", "0001_initial"),
        # replace this with the latest migration in contrib.auth
        ("auth", "####_migration_name"),
    ]

    operations = [
        migrations.RunPython(forwards_func),
    ]
```

このマイグレーションには、ハードウェアの速度にもよりますが、数千人のユーザーで数分かかることに注意してください。

最後に [`PASSWORD_HASHERS`](/ja/6.0/ref/settings/#std-setting-PASSWORD_HASHERS) 設定を追加します:

*`mysite/settings.py`*

```python
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "accounts.hashers.PBKDF2WrappedMD5PasswordHasher",
]
```

あなたのサイトが使用している他のハッシャーもこのリストに含めてください。

### Django に含まれるハッシャー

Django に含まれるハッシャーの全リストは以下の通りです:

```
[
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    "django.contrib.auth.hashers.BCryptPasswordHasher",
    "django.contrib.auth.hashers.ScryptPasswordHasher",
    "django.contrib.auth.hashers.MD5PasswordHasher",
]
```

対応するアルゴリズム名は以下の通りです:

- `pbkdf2_sha256`
- `pbkdf2_sha1`
- `argon2`
- `bcrypt_sha256`
- `bcrypt`
- `scrypt`
- `md5`

### 独自のハッシャーを書く

イテレーション回数のようなワークファクターを含む独自のパスワードハッシャーを書く場合は、 `harden_runtime(self, password, encoded)` メソッドを実装して、 `エンコードされた` パスワードに指定されたワークファクターとハッシャーのデフォルトのワークファクターとの間のランタイムギャップを埋める必要があります。これにより、古いイテレーション数でエンコードされたパスワードを持つユーザーと存在しないユーザー（デフォルトのハッシャーのデフォルトのイテレーション数で実行される）のログイン要求の違いによるユーザー列挙タイミング攻撃を防ぐことができます。

PBKDF2 を例にとると、 `encoded` が 20,000 回のイテレーションを含み、ハッシャーのデフォルトの `iterations` が 30,000 回である場合、このメソッドは `password` を PBKDF2 のさらに 10,000 回のイテレーションに通す必要があります。

もしあなたのハッシャーがワークファクターを持っていない場合は、このメソッドを何もしない操作 (`pass`) として実装してください。

## ユーザーのパスワードを手動で管理する

[`django.contrib.auth.hashers`](#module-django.contrib.auth.hashers) モジュールは、ハッシュ化されたパスワードを作成・検証するための関数群を提供します。これらは `User` モデルとは独立して使用できます。

#### `check_password(password, encoded, setter=None, preferred='default')`

#### `acheck_password(password, encoded, asetter=None, preferred='default')`

*非同期バージョン*: `acheck_password()`

If you'd like to manually authenticate a user by comparing a plaintext
password to the hashed password in the database, use the convenience
function [`check_password()`](#django.contrib.auth.hashers.check_password). It takes two mandatory arguments: the
plaintext password to check, and the full value of a user's `password`
field in the database to check against. It returns `True` if they match,
`False` otherwise. Optionally, you can pass a callable `setter` that
takes the password and will be called when you need to regenerate it. You
can also pass `preferred` to change a hashing algorithm if you don't want
to use the default (first entry of `PASSWORD_HASHERS` setting). See
[Django に含まれるハッシャー](#auth-included-hashers) for the algorithm name of each hasher.

#### `make_password(password, salt=None, hasher='default')`

Creates a hashed password in the format used by this application. It takes
one mandatory argument: the plaintext password (string or bytes).
Optionally, you can provide a salt and a hashing algorithm to use, if you
don't want to use the defaults (first entry of `PASSWORD_HASHERS`
setting). See [Django に含まれるハッシャー](#auth-included-hashers) for the algorithm name of each
hasher. If the password argument is `None`, an unusable password is
returned (one that will never be accepted by [`check_password()`](#django.contrib.auth.hashers.check_password)).

#### `is_password_usable(encoded_password)`

パスワードが [`User.set_unusable_password()`](/ja/6.0/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password) の結果の場合は `False` を返します。

## パスワードの妥当性検証

ユーザーは、良くないパスワードを選択することがあります。この問題を軽減するために、Djangoはプラガブルなパスワードの妥当性検証を提供しています。複数のパスワードの妥当性検証を同時に設定できます。いくつかのバリデータは Django に含まれていますが、自分で書くこともできます。

各パスワードのバリデータは、ユーザーに要件の説明文を与え、指定されたパスワードの妥当性検証を行い、要件を満たしていない場合はエラーメッセージを返し、オプションでユーザのパスワードが変更されたときに通知するコールバックを定義します。バリデータは、動作を細かく指定するためのオプション設定を持つこともできます。

妥当性検証は [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) の設定で管理されます。設定のデフォルトは、空のリストになってます。これは、ひとつもバリデータが適用されていないことを意味しています。 [`startproject`](/ja/6.0/ref/django-admin/#django-admin-startproject) を使用して作られた新しいプロジェクトでは、バリデータのセットはデフォルトで有効になっています。

デフォルトでは、バリデータはパスワードをリセットまたは変更するフォームと [`createsuperuser`](/ja/6.0/ref/django-admin/#django-admin-createsuperuser) と [`changepassword`](/ja/6.0/ref/django-admin/#django-admin-changepassword) 管理コマンドで使用されます。たとえば、 `User.objects.create_user()` や `create_superuser()` のようなモデルレベルではバリデータは適用されません。なぜなら、このレベルで Django とやりとりするのはユーザ ではなく開発者であると想定しているからであり、また、モデルのバリデーションがモデル作成の一環として自動的に実行されるわけではないからです。

> **Note**
>
> パスワードの妥当性検証は多くの脆弱なパスワードの形式が使用されることを防ぎます。しかしながら、パスワードが全てのバリデータを通過するという事実は、強力なパスワードであることを保証するわけではありません。最も先進的なパスワードのバリデータでさえ検出できない、パスワードを弱めうる多くの要素があります。

### パスワードの妥当性検証を有効にする

パスワードの妥当性検証は [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) で構成されます:

```
AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
        "OPTIONS": {
            "min_length": 9,
        },
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]
```

本例では組み込みの4つ全てのバリデータを有効化します。

- `UserAttributeSimilarityValidator` は、パスワードとユーザの属性との類似性をチェックします。
- `MinimumLengthValidator` は、パスワードが最小の長さを満たしているかをチェックします。このバリデータはカスタムオプションで構成されます。現在の設定では、最小長さは、デフォルトの8文字ではなく、9文字になっています。
- `CommonPasswordValidator` は、一般的なパスワードのリストにそのパスワードが入っていないかをチェックします。デフォルトでは、組み込まれた20,000個のパスワードのリストと比較します。
- `NumericPasswordValidator` は、パスワードが全体的に数値ではないかをチェックします。

`UserAttributeSimilarityValidator` と `CommonPasswordValidator` については、たとえばこの例ではデフォルトの設定を使用しています。 `NumericPasswordValidator` には設定はありません。

パスワードバリデーションのヘルプテキストとエラーは、常に [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) に記載されているソート順に返されます。

### Django に含まれるバリデータ

Django には 4 つのバリデータがあります:

#### `class MinimumLengthValidator(min_length=8)`

パスワードが最小限の長さであることを検証します。最小の長さは `min_length` パラメータでカスタマイズできます。

#### `get_error_message()`

> **New in Django 5.2**

`ValidationError` のエラーメッセージをカスタマイズするためのフックです。デフォルトでは `"This password is too short. It must contain at least <min_length> characters."` （和訳：「このパスワードは短すぎます。最低 \<min\_length\> 文字以上必要です。」）というメッセージが使用されます。

#### `get_help_text()`

バリデーターのヘルプテキストをカスタマイズするためのフックです。デフォルトでは `"Your password must contain at least <min_length> characters."` （和訳：「パスワードは最低 \<min\_length\> 文字以上必要です。」）が使用されます。

#### `class UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7)`

パスワードがユーザの特定の属性と十分に異なることを検証します。

パラメータ `user_attributes` は、比較するユーザー属性の名前のイテラブルでなければなりません。この引数が指定されない場合、デフォルトが使用されます。`'username', 'first_name', 'last_name', 'email'` です。存在しない属性は無視されます。

パスワードの最大類似度は `max_similarity` パラメータで 0.1 から 1.0 の範囲で指定できます。これは [`difflib.SequenceMatcher.quick_ratio()`](https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.quick_ratio) の結果と比較されます。0.1の値を指定すると、 `user_attributes` と大幅に異なるパスワード以外は拒否され、1.0の値を指定すると、属性の値と同じパスワードのみが拒否されます。

#### `get_error_message()`

> **New in Django 5.2**

`ValidationError` のエラーメッセージをカスタマイズするためのフックです。デフォルトでは `"The password is too similar to the <user_attribute>."` （和訳：「このパスワードは \<user\_attribute\> と似すぎています。」）が使用されます。

#### `get_help_text()`

バリデーターのヘルプテキストをカスタマイズするためのフックです。デフォルトでは `"Your password can’t be too similar to your other personal information."` （和訳: 「あなたの他の個人情報と似ているパスワードにはできません。」）が使用されます。

#### `class CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH)`

Validates that the password is not a common password. This converts the
password to lowercase (to do a case-insensitive comparison) and checks it
against a list of 20,000 common passwords created by [Royce Williams](https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce).

`password_list_path` には一般的なパスワードのカスタムファイルのパスを指定できます。このファイルには1行につき1つの小文字のパスワードが含まれている必要があり、プレーンテキストまたはgzip圧縮されている必要があります。

#### `get_error_message()`

> **New in Django 5.2**

`ValidationError` のエラーメッセージをカスタマイズするためのフックです。デフォルトでは `"This password is too common."` （和訳: 「このパスワードは一般的すぎます。」）が使用されます。

#### `get_help_text()`

バリデーターのヘルプテキストをカスタマイズするためのフックです。 デフォルトでは "Your password can’t be a commonly used password."（和訳: 「よく使われるパスワードにはできません。」）が使用されます。

#### `class NumericPasswordValidator`

パスワードが数字のみでないことを確認します。

#### `get_error_message()`

> **New in Django 5.2**

`ValidationError` のエラーメッセージをカスタマイズするためのフックです。 デフォルトでは `"This password is entirely numeric."` （和訳: 「このパスワードは数字しか使われていません。」）が使用されます。

#### `get_help_text()`

バリデーターのヘルプテキストをカスタマイズするためのフックです。 デフォルトでは `"Your password can’t be entirely numeric."` （和訳: 「数字だけのパスワードにはできません。」）が使用されます。

### バリデーションの統合

`django.contrib.auth.password_validation` には、独自のフォームや他のコードから呼び出して パスワード認証を統合できる関数がいくつかあります。これは、たとえばパスワードの設定にカスタムフォームを使ったり、 パスワードの設定を許可する API 呼び出しがある場合に便利です。

#### `validate_password(password, user=None, password_validators=None)`

パスワードを検証します。すべてのバリデータがパスワードを有効と判定した場合、 `None` を返します。1つ以上のバリデータがパスワードを拒否した場合、バリデータからのすべてのエラーメッセージと共に [`ValidationError`](/ja/6.0/ref/exceptions/#django.core.exceptions.ValidationError) を発生させます。

もし `user` オブジェクトを指定しなかった場合、バリデータによってはバリデーションを実行できず、任意のパスワードを受け取ってしまう可能性があります。

#### `password_changed(password, user=None, password_validators=None)`

パスワードが変更されたことをすべてのバリデータに通知します。これは、パスワードの再利用を防止するバリデータなどで使用します。パスワードの変更に成功したら、これを呼び出さなければなりません。

[`AbstractBaseUser`](/ja/6.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser) のサブクラスでは、パスワードフィールドは [`set_password()`](/ja/6.0/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.set_password) を呼び出すと "dirty" としてマークされ、ユーザが保存された後に `password_changed()` が呼び出されます。

#### `password_validators_help_texts(password_validators=None)`

すべてのバリデータのヘルプテキストの一覧を返します。これらは、パスワードの条件をユーザに説明するものです。

#### `password_validators_help_text_html(password_validators=None)`

すべてのヘルプテキストを `<ul>` で囲んだ HTML 文字列を返します。これはフォームにパスワードバリデーションを追加する際に便利です。フォームフィールドの `help_text` パラメータに直接出力を渡すことができるからです。

#### `get_password_validators(validator_config)`

パラメータ `validator_config` に基づいてバリデータオブジェクトのセットを返します。デフォルトでは、すべての関数は [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) で定義されたバリデータを使用しますが、この関数を別のバリデータセットで呼び出して、その結果を他の関数の `password_validators` パラメータに渡すことで、カスタムバリデータセットを代わりに使用できます。これは、たいていの場面で使用する典型的なバリデータセットがありながら、 特別な場面で独自のバリデータセットが必要になる場合に便利です。常に同じバリデータを使う場合は、この関数を使う必要はありません。 [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) の設定がデフォルトで使われるからです。

`validator_config` の構造は [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) の構造と同じです。この関数の戻り値は上記の関数の `password_validators` パラメータに渡すことができます。

これらの関数にパスワードが渡される場合は、ハッシュ化されたパスワードではなく、常に平文のパスワードでなければならないことに注意してください。

### 独自のバリデータを書く

Django の組み込みバリデータでは不十分な場合、自分でパスワードバリデータ を書くことができます。バリデータはとても小さなインタフェースを持っています。2 つのメソッドを実装しなければなりません:

- `validate(self, password, user=None)`: パスワードを検証します。パスワードが有効な場合は `None` を返し、パスワードが無効な場合はエラーメッセージと共に [`ValidationError`](/ja/6.0/ref/exceptions/#django.core.exceptions.ValidationError) を発生させます。もし `user` が `None` であった場合、バリデータが実行できないので、 `None` を返してエラーにならないようにしてください。
- `get_help_text()`: ユーザに要件を説明するためのヘルプテキストを提供します。

バリデータの [`AUTH_PASSWORD_VALIDATORS`](/ja/6.0/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS) の `OPTIONS` にあるすべての項目がコンストラクタに渡されます。コンストラクタの引数にはデフォルト値を指定します。

以下は、1つのオプション設定を持つ基本的なバリデータの例です。

```
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _

class MinimumLengthValidator:
    def __init__(self, min_length=8):
        self.min_length = min_length

    def validate(self, password, user=None):
        if len(password) < self.min_length:
            raise ValidationError(
                _("This password must contain at least %(min_length)d characters."),
                code="password_too_short",
                params={"min_length": self.min_length},
            )

    def get_help_text(self):
        return _(
            "Your password must contain at least %(min_length)d characters."
            % {"min_length": self.min_length}
        )
```

パスワードの変更が成功した後に呼び出される `password_changed(password, user=None`) を実装することもできます。これはたとえばパスワードの再利用を防ぐために使用できます。しかし、ユーザーの以前のパスワードを保存することにした場合、決して平文で保存してはいけません。
