{"title":"Djangoにおけるパスワード管理","version":"5.1","locale":"ja","docname":"topics/auth/passwords","url":"/ja/5.1/topics/auth/passwords/","canonical":"https://djangodocs.dev/ja/5.1/topics/auth/passwords/","summary":"パスワード管理は一般的に、不必要に再発明されるべきではないものです。Djangoはユーザーのパスワードを管理するための安全で柔軟なツールセットを提供するよう努めています。このドキュメントでは、Djangoがパスワードを保存する方法、ストレージハッシュの設定方法、およびハッシュされたパスワードを扱ういくつかのユーティリティについて…","html":"<h1>Djangoにおけるパスワード管理<a class=\"heading-anchor\" href=\"#password-management-in-django\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>パスワード管理は一般的に、不必要に再発明されるべきではないものです。Djangoはユーザーのパスワードを管理するための安全で柔軟なツールセットを提供するよう努めています。このドキュメントでは、Djangoがパスワードを保存する方法、ストレージハッシュの設定方法、およびハッシュされたパスワードを扱ういくつかのユーティリティについて説明します。</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">参考</p>\n<p>ユーザーが強力なパスワードを使ったとしても、攻撃者が通信経路上において盗聴をおこなう可能性があります。パスワード (または他の機密データ) がプレーンな HTTP コネクションで送信されないように、 <a class=\"reference internal\" href=\"/ja/5.1/topics/security/#security-recommendation-ssl\"><span class=\"std std-ref\">HTTPS</span></a> を使用してください。なぜなら、HTTP はパスワードスニッフィングに対して脆弱であるからです。</p>\n</aside>\n<section id=\"how-django-stores-passwords\">\n<span id=\"auth-password-storage\"></span><h2>Djangoのパスワード保存方法<a class=\"heading-anchor\" href=\"#how-django-stores-passwords\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>DjangoはデフォルトでPBKDF2を利用した、柔軟なパスワード保存システムを提供します。</p>\n<p><a class=\"reference internal\" href=\"/ja/5.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> オブジェクトの <a class=\"reference internal\" href=\"/ja/5.1/ref/contrib/auth/#django.contrib.auth.models.User.password\" title=\"django.contrib.auth.models.User.password\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">password</span></code></a> 属性は、次のような形式の文字列です。</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>&lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;$&lt;hash&gt;\n</code></pre></div>\n<p>これらはユーザーのパスワードを保存するためのコンポーネントで、ハッシュアルゴリズム、アルゴリズムのイテレーション回数（ワークファクター）、ランダムなソルト、そして結果のパスワードハッシュをドル記号($)で区切ったものです。このアルゴリズムは、Djangoが使用できる数多くの一方向ハッシュ、またはパスワード保存アルゴリズム（下記参照）の一つです。イテレーションはハッシュに対してアルゴリズムが実行された回数を表します。ソルトは使用されたランダムシードで、ハッシュは一方向ハッシュ関数の実行結果です。</p>\n<p>デフォルトでは、Djangoは <a class=\"reference external\" href=\"https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf\">NIST</a> が推奨するパスワードストレッチングメカニズムである <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/PBKDF2\">PBKDF2</a> アルゴリズムと SHA256 ハッシュを使用します。これはほとんどのユーザーに十分有効なはずです。非常に安全で、クラックするのに膨大な計算時間を必要とします。</p>\n<p>ただし、要件に応じて、異なるアルゴリズムを使用することも、一部のセキュリティ状況に合わせてカスタムアルゴリズムを使用することもできます。繰り返しますが、ほとんどのユーザーはこれを行う必要はありません。よくわからない場合、おそらくそうしないほうが良いです。もしそうする場合は、こちらをお読みください:</p>\n<p>Django は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> 設定を参照して、使用するアルゴリズムを選択します。これは、この Django インストールがサポートしているハッシュアルゴリズムクラスのリストです。</p>\n<p>パスワードの保存には、 Django は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> の最初のハッシャーを使います。別のアルゴリズムで新しいパスワードを保存するには、 <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> にあなたの好きなアルゴリズムを最初に書いてください。</p>\n<p>パスワードの検証のために、 Django は保存されたパスワードのアルゴリズム名と一致するハッ シャーをリストの中から探します。保存されたパスワードが <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> にないアルゴリズ ム名を持つ場合、それを検証しようとすると <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueError</span></code> が発生します。</p>\n<p>デフォルトでの <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a></p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>これは、Djangoは <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/PBKDF2\">PBKDF2</a> を使用して全てのパスワードを保存しますが、PBKDF2SHA1、 <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">argon2</a> 、および <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Bcrypt\">bcrypt</a> で保存されたパスワードのチェックもサポートすることを意味しています。</p>\n<p>次のいくつかのセクションでは、高度なユーザーがこの設定を変更するための一般的な方法について説明します。</p>\n<section id=\"using-argon2-with-django\">\n<span id=\"argon2-usage\"></span><h3>Django で Argon2 を使う<a class=\"heading-anchor\" href=\"#using-argon2-with-django\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> は、次世代ハッシュアルゴリズムを選定するコミュニティ主催のオープンコンペティションである、2015年の <a class=\"reference external\" href=\"https://www.password-hashing.net/\">Password Hashing Competition</a> の優勝者です。カスタムハードウェアで計算しても、通常のCPUで計算するよりも有利にならないように設計されています。Argon2パスワードハッシュのデフォルトのバリアントはArgon2idです。</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> はサードパーティのライブラリを必要とするため、 Django のデフォルトではありません。しかし、 Password Hashing Competition パネルでは、 Django がサポートしている他のアルゴリズムではなく、 Argon2 をすぐに使うことを推奨しています。</p>\n<p>Argon2idをデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:</p>\n<ol class=\"arabic\">\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/argon2-cffi/\">argon2-cffi</a> パッケージをインストールしてください。 <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">django[argon2]</span></code> コマンドでインストールできます。このコマンドは、<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">argon2-cffi</span></code> と同等ですが、Djangoの <code class=\"docutils literal notranslate\"><span class=\"pre\">pyproject.toml</span></code> に記載されているバージョン要件が考慮されます。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> を変更して、<code class=\"docutils literal notranslate\"><span class=\"pre\">Argon2PasswordHasher</span></code> を最初にリストアップします。つまり、設定ファイルに下記のように書きます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Django に <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">パスワードのアップグレード</span></a> をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。</p>\n</li>\n</ol>\n</section>\n<section id=\"using-bcrypt-with-django\">\n<span id=\"bcrypt-usage\"></span><h3>Django で <code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt</span></code> を使う<a class=\"heading-anchor\" href=\"#using-bcrypt-with-django\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Bcrypt\">Bcrypt</a> は一般的なパスワード保存アルゴリズムで、特にパスワードの長期保存用に設計されています。サードパーティのライブラリを使う必要があるため、 Django がデフォルトで使うものではありませんが、多くの人が使いたいでしょうから、 Django は最小限の労力で bcrypt をサポートしています。</p>\n<p>Bcrypt をデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:</p>\n<ol class=\"arabic\">\n<li><p><a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/bcrypt/\">bcrypt</a> パッケージをインストールしてください。 <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">django[bcrypt]</span></code> コマンドでインストールできます。このコマンドは、<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">bcrypt</span></code> と同等ですが、Djangoの <code class=\"docutils literal notranslate\"><span class=\"pre\">pyproject.toml</span></code> に記載されているバージョン要件が考慮されます。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> を変更して、<code class=\"docutils literal notranslate\"><span class=\"pre\">BCryptSHA256PasswordHasher</span></code> を最初にリストアップします。つまり、設定ファイルに下記のように書きます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Django に <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">パスワードのアップグレード</span></a> をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。</p>\n</li>\n</ol>\n<p>これで Django はデフォルトのストレージアルゴリズムとして Bcrypt を使うようになります。</p>\n</section>\n<section id=\"using-scrypt-with-django\">\n<span id=\"scrypt-usage\"></span><h3>Django で <code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> を使う<a class=\"heading-anchor\" href=\"#using-scrypt-with-django\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> は、ブルートフォース攻撃を減速させるために設定されたイテレーション数を利用するという点で、PBKDF2やbcryptと似ています。しかし、PBKDF2とbcryptは多くのメモリを必要としないため、十分なリソースを持つ攻撃者は、攻撃プロセスを高速化するために大規模な並列攻撃を仕掛けることができます。 <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> は、攻撃者が使用できる並列処理の量を制限するために、他のパスワードベースの鍵導出関数と比較してより多くのメモリを使用するように特別に設計されています。</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> をデフォルトのストレージアルゴリズムとして使用するには、以下のようにします:</p>\n<ol class=\"arabic\">\n<li><p><a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> を変更して、<code class=\"docutils literal notranslate\"><span class=\"pre\">ScryptPasswordHasher</span></code> を最初にリストアップします。つまり、設定ファイルに下記のように書きます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Django に <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">パスワードのアップグレード</span></a> をさせる必要がある場合は、このリストにエントリを残すまたは追加してください。</p>\n</li>\n</ol>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> はOpenSSL 1.1+を必要とします。</p>\n</aside>\n</section>\n<section id=\"increasing-the-salt-entropy\">\n<h3>ソルトのエントロピーを増加させる<a class=\"heading-anchor\" href=\"#increasing-the-salt-entropy\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>ほとんどのパスワードハッシュはレインボーテーブル攻撃から守るために、パスワードハッシュと一緒にソルトを含んでいます。ソルトはランダムな値であり、レインボーテーブルのサイズとコストを増加させます。現在は <code class=\"docutils literal notranslate\"><span class=\"pre\">BasePasswordHasher</span></code> の <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> 値で128ビットに設定されています。計算機やストレージのコストが下がれば、この値を上げる必要があります。独自のパスワードハッシュを実装する場合、パスワードハッシュに希望するエントロピーレベルを使用するために、この値を自由に上書きできます。 <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> の単位はビットです。</p>\n<aside class=\"admonition-implementation-detail admonition\">\n<p class=\"admonition-title\">実装の詳細</p>\n<p>ソルト値が保存されるメカニズムにより、 <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> 値は実際には最小値です。たとえば、128という値は実際には131ビットのエントロピーを含むソルトを提供します。</p>\n</aside>\n</section>\n<section id=\"increasing-the-work-factor\">\n<span id=\"increasing-password-algorithm-work-factor\"></span><h3>work factor を増やす<a class=\"heading-anchor\" href=\"#increasing-the-work-factor\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"pbkdf2-and-bcrypt\">\n<h4>PBKDF2 と bcrypt<a class=\"heading-anchor\" href=\"#pbkdf2-and-bcrypt\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>PBKDF2 と bcrypt アルゴリズムは、ハッシュ化に何度もイテレート（ラウンド）します。これは意図的に攻撃者の速度を低下させ、ハッシュ化されたパスワードに対する攻撃を困難にします。しかし、計算能力が上がるにつれて、イテレーションの回数を増やす必要があります。私たちは妥当なデフォルト値を選びました（そして Django のリリー スごとに増やす予定です）が、セキュリティの必要性や利用可能な処理能力に応じて、上げたり下げたりすることもできます。そのためには、適切なアルゴリズムをサブクラス化し、 <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> パラメータをオーバーライドします (bcrypt hasher をサブクラス化するときは <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> パラメータを使います)。たとえば、デフォルトの PBKDF2 アルゴリズムで使用するイテレーションの回数を増やすには、次のようにします:</p>\n<ol class=\"arabic\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.hashers.PBKDF2PasswordHasher</span></code> のサブクラスを作成します:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.hashers</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">PBKDF2PasswordHasher</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyPBKDF2PasswordHasher</span><span class=\"p\">(</span><span class=\"n\">PBKDF2PasswordHasher</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"n\">iterations</span> <span class=\"o\">=</span> <span class=\"n\">PBKDF2PasswordHasher</span><span class=\"o\">.</span><span class=\"n\">iterations</span> <span class=\"o\">*</span> <span class=\"mi\">100</span>\n</code></pre></div>\n<p>これをプロジェクトのどこかに保存します。たとえば、 <code class=\"docutils literal notranslate\"><span class=\"pre\">myproject/hashers.py</span></code> のようなファイルに保存します。</p>\n</li>\n<li><p>新しいハッシャーを <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> の最初のエントリーとして追加します:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;myproject.hashers.MyPBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ol>\n<p>これで Django が PBKDF2 を使ってパスワードを保存する際に、より多くのイテレーションを使うようになります。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>bcrypt の <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> は対数の work factor で、たとえば 12 ラウンドは <code class=\"docutils literal notranslate\"><span class=\"pre\">2</span> <span class=\"pre\">**</span> <span class=\"pre\">12</span></code> のイテレーションを意味します。</p>\n</aside>\n</section>\n<section id=\"argon2\">\n<h4>Argon2<a class=\"heading-anchor\" href=\"#argon2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Argon2には、カスタマイズ可能な以下の属性があります:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> はハッシュ内のイテレートする回数をコントロールします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> は、ハッシュの計算に必要なメモリのサイズをコントロールします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> はハッシュの計算をいくつのCPUで並列化できるかを制御します。</p></li>\n</ol>\n<p>これらの属性のデフォルト値は、おそらく問題ないでしょう。パスワード・ハッシュが速すぎたり遅すぎたりすると判断した場合は、以下のように微調整できます:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> は、ハッシュを計算するスレッド数を指定します。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> には、余裕を持ったメモリのKiBを選択してください。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> を調整し、パスワードのハッシュにかかる時間を測定します。 <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> は、あなたにとって許容できる時間を選んでください。もし <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> に 1 を指定しても許容できないほど遅い場合は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> を下げてください。</p></li>\n</ol>\n<aside class=\"admonition-memory-cost-interpretation admonition\">\n<p class=\"admonition-title\"><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> の解釈</p>\n<p>argon2 コマンドラインユーティリティと他のいくつかのライブラリは、 <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> パラメータを Django が使う値とは異なる解釈をします。変換は <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span> <span class=\"pre\">==</span> <span class=\"pre\">2</span> <span class=\"pre\">**</span> <span class=\"pre\">memory_cost_commandline</span></code> で行います。</p>\n</aside>\n</section>\n<section id=\"scrypt\">\n<h4><code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code><a class=\"heading-anchor\" href=\"#scrypt\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> にはカスタマイズ可能な以下の属性があります:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">work_factor</span></code> はハッシュ内のイテレートする回数をコントロールします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> はいくつのスレッドが並列に実行されるかをコントロールします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> はハッシュの計算中に使用できるメモリの最大サイズを制限します。デフォルトは <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code> で、OpenSSL ライブラリによるデフォルトの制限を意味します。</p></li>\n</ol>\n<p>私たちは合理的なデフォルト値を選びましたが、セキュリティのニーズや利用可能な処理能力に応じて、調整することもできます。</p>\n<aside class=\"admonition-estimating-memory-usage admonition\">\n<p class=\"admonition-title\">メモリ使用量の見積もり</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> に必要な最小のメモリサイズは以下の通りです:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">work_factor</span> <span class=\"o\">*</span> <span class=\"mi\">2</span> <span class=\"o\">*</span> <span class=\"n\">block_size</span> <span class=\"o\">*</span> <span class=\"mi\">64</span>\n</code></pre></div>\n<p>そのため、 <code class=\"docutils literal notranslate\"><span class=\"pre\">work_factor</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code> の値を変更する際には <code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> を調整する必要があるかもしれません。</p>\n</aside>\n</section>\n</section>\n<section id=\"password-upgrading\">\n<span id=\"password-upgrades\"></span><h3>パスワードのアップグレード<a class=\"heading-anchor\" href=\"#password-upgrading\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>ユーザーがログインする際、もしそのパスワードが推奨されるアルゴリズム以外で保存されていた場合、Djangoは自動で推奨されるアルゴリズムへ更新します。つまり、Djangoの古いインストールでも、ユーザーのログイン時に自動的にセキュリティが強化され、新しい（より良い）保存アルゴリズムが開発されるたびに切り替えることができるということです。</p>\n<p>ただし、Djangoは  <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> で定義されたアルゴリズムを使用するパスワードしか更新できません。そのため、新しいシステムにアップグレードする際には絶対にこのリストからエントリを「削除」しないでください。そうしないと、定義されてないアルゴリズムを使用するユーザーのパスワードを更新できなくなります。ハッシュされたパスワードは、PBKDF2のイテレーション回数、bcrypt のラウンド数、または argon2 の属性数を増やす (または減らす) と更新されます。</p>\n<p>データベース上の全てのパスワードがデフォルトのハッシュアルゴリズムでエンコードされていない場合、デフォルト以外のアルゴリズムでエンコードされたパスワードを持つユーザーと、存在しないユーザー（デフォルトのハッシュアルゴリズムが実行されます）に対するログインリクエストにかかる時間の差に起因する、ユーザー列挙型タイミング攻撃に対して脆弱になる可能性があることに注意してください。 <a class=\"reference internal\" href=\"#wrapping-password-hashers\"><span class=\"std std-ref\">古いパスワードハッシュの更新</span></a> によりこれを軽減できます。</p>\n</section>\n<section id=\"password-upgrading-without-requiring-a-login\">\n<span id=\"wrapping-password-hashers\"></span><h3>ログインを必要としないパスワードアップグレード<a class=\"heading-anchor\" href=\"#password-upgrading-without-requiring-a-login\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>既存のデータベースが MD5 のような古くて弱いハッシュを使用している場合、ユーザがログインしたときにハッシュのアップグレードが行われるのを待つのではなく、自分でハッシュをアップグレードしたいと思うかもしれません (ユーザがサイトに戻ってこない場合は、アップグレードが行われないかもしれません)。この場合、「ラップ」パスワードハッシュを使用できます。</p>\n<p>この例では、PBKDF2(MD5(password)) を使用するように MD5 ハッシュのコレクションをマイグレーションし、ユーザがログイン時に正しいパスワードを入力したかどうかをチェックするために、対応するパスワードハッシュを追加します。組み込みの <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> モデルを使用しており、プロジェクトには <code class=\"docutils literal notranslate\"><span class=\"pre\">accounts</span></code> アプリがあると仮定します。このパターンをカスタマイズすることで、任意のアルゴリズムやカスタムユーザモデルで動作させることができます。</p>\n<p>まず、独自のハッシャーを追加します:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">accounts/hashers.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.hashers</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"p\">(</span>\n    <span class=\"n\">PBKDF2PasswordHasher</span><span class=\"p\">,</span>\n    <span class=\"n\">MD5PasswordHasher</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PBKDF2WrappedMD5PasswordHasher</span><span class=\"p\">(</span><span class=\"n\">PBKDF2PasswordHasher</span><span class=\"p\">):</span>\n    <span class=\"n\">algorithm</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;pbkdf2_wrapped_md5&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">encode_md5_hash</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">md5_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">encode</span><span class=\"p\">(</span><span class=\"n\">md5_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"n\">_</span><span class=\"p\">,</span> <span class=\"n\">_</span><span class=\"p\">,</span> <span class=\"n\">md5_hash</span> <span class=\"o\">=</span> <span class=\"n\">MD5PasswordHasher</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">encode</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s2\">&quot;$&quot;</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">encode_md5_hash</span><span class=\"p\">(</span><span class=\"n\">md5_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>データマイグレーションは次のようになります:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">accounts/migrations/0002_migrate_md5_passwords.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">migrations</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">..hashers</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">PBKDF2WrappedMD5PasswordHasher</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">forwards_func</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"n\">User</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s2\">&quot;auth&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;User&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">users</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">password__startswith</span><span class=\"o\">=</span><span class=\"s2\">&quot;md5$&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">hasher</span> <span class=\"o\">=</span> <span class=\"n\">PBKDF2WrappedMD5PasswordHasher</span><span class=\"p\">()</span>\n    <span class=\"k\">for</span> <span class=\"n\">user</span> <span class=\"ow\">in</span> <span class=\"n\">users</span><span class=\"p\">:</span>\n        <span class=\"n\">algorithm</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">md5_hash</span> <span class=\"o\">=</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">password</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s2\">&quot;$&quot;</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">password</span> <span class=\"o\">=</span> <span class=\"n\">hasher</span><span class=\"o\">.</span><span class=\"n\">encode_md5_hash</span><span class=\"p\">(</span><span class=\"n\">md5_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">update_fields</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s2\">&quot;password&quot;</span><span class=\"p\">])</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s2\">&quot;accounts&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;0001_initial&quot;</span><span class=\"p\">),</span>\n        <span class=\"c1\"># replace this with the latest migration in contrib.auth</span>\n        <span class=\"p\">(</span><span class=\"s2\">&quot;auth&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;####_migration_name&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">forwards_func</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></figure>\n<p>このマイグレーションには、ハードウェアの速度にもよりますが、数千人のユーザーで数分かかることに注意してください。</p>\n<p>最後に <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> 設定を追加します:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;accounts.hashers.PBKDF2WrappedMD5PasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>あなたのサイトが使用している他のハッシャーもこのリストに含めてください。</p>\n</section>\n<section id=\"included-hashers\">\n<span id=\"auth-included-hashers\"></span><h3>Django に含まれるハッシャー<a class=\"heading-anchor\" href=\"#included-hashers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django に含まれるハッシャーの全リストは以下の通りです:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"p\">[</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.Argon2PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.BCryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.ScryptPasswordHasher&quot;</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;django.contrib.auth.hashers.MD5PasswordHasher&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>対応するアルゴリズム名は以下の通りです:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">pbkdf2_sha256</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">pbkdf2_sha1</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">argon2</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt_sha256</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">md5</span></code></p></li>\n</ul>\n</section>\n<section id=\"writing-your-own-hasher\">\n<span id=\"write-your-own-password-hasher\"></span><h3>独自のハッシャーを書く<a class=\"heading-anchor\" href=\"#writing-your-own-hasher\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>イテレーション回数のようなワークファクターを含む独自のパスワードハッシャーを書く場合は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">harden_runtime(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">encoded)</span></code> メソッドを実装して、 <code class=\"docutils literal notranslate\"><span class=\"pre\">エンコードされた</span></code> パスワードに指定されたワークファクターとハッシャーのデフォルトのワークファクターとの間のランタイムギャップを埋める必要があります。これにより、古いイテレーション数でエンコードされたパスワードを持つユーザーと存在しないユーザー（デフォルトのハッシャーのデフォルトのイテレーション数で実行される）のログイン要求の違いによるユーザー列挙タイミング攻撃を防ぐことができます。</p>\n<p>PBKDF2 を例にとると、 <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> が 20,000 回のイテレーションを含み、ハッシャーのデフォルトの <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> が 30,000 回である場合、このメソッドは <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> を PBKDF2 のさらに 10,000 回のイテレーションに通す必要があります。</p>\n<p>もしあなたのハッシャーがワークファクターを持っていない場合は、このメソッドを何もしない操作 (<code class=\"docutils literal notranslate\"><span class=\"pre\">pass</span></code>) として実装してください。</p>\n</section>\n</section>\n<section id=\"module-django.contrib.auth.hashers\">\n<span id=\"manually-managing-a-user-s-password\"></span><h2>ユーザーのパスワードを手動で管理する<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.hashers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"#module-django.contrib.auth.hashers\" title=\"django.contrib.auth.hashers\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.hashers</span></code></a> モジュールは、ハッシュ化されたパスワードを作成・検証するための関数群を提供します。これらは <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> モデルとは独立して使用できます。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.check_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">check_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">encoded</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">setter</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">preferred</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'default'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.check_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.acheck_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">acheck_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">encoded</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">asetter</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">preferred</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'default'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.acheck_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>非同期バージョン</em>: <code class=\"docutils literal notranslate\"><span class=\"pre\">acheck_password()</span></code></p>\n<p>もしプレーンテキストのパスワードとデータベースのハッシュ化されたパスワードを比較して手動でユーザーを認証したい場合は、 <a class=\"reference internal\" href=\"#django.contrib.auth.hashers.check_password\" title=\"django.contrib.auth.hashers.check_password\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">check_password()</span></code></a> という便利な関数を使用してください。この関数は2つの必須引数を取ります。チェックするプレーンテキストのパスワードと、照合するデータベースの <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> フィールドの完全な値です。これらが一致すれば <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> を返し、一致しなければ <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> を返します。オプションとして、呼び出し可能な <code class=\"docutils literal notranslate\"><span class=\"pre\">setter</span></code> を渡すことができます。この <code class=\"docutils literal notranslate\"><span class=\"pre\">setter</span></code> はパスワードを受け取り、再生成の必要がある際に呼び出されます。また、デフォルトのハッシュアルゴリズム (<code class=\"docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code> 設定の最初のエントリ) を使用したくない場合は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">preferred</span></code> を渡せばハッシュアルゴリズムを変更できます。各ハッシャーのアルゴリズム名については <a class=\"reference internal\" href=\"#auth-included-hashers\"><span class=\"std std-ref\">Django に含まれるハッシャー</span></a> を参照してください。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.0\">\n<p class=\"version-note-title\">Changed in Django 5.0</p><p><code class=\"docutils literal notranslate\"><span class=\"pre\">acheck_password()</span></code> メソッドが追加されました。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.make_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">make_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">salt</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">hasher</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'default'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.make_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>このアプリケーションで使用する形式でハッシュ化されたパスワードを作成します。必須引数は1つで、プレーンテキスト(文字列またはバイト)のパスワードです。オプションとして、デフォルトを使用したくない場合に使用するソルトとハッシュアルゴリズムを指定できます (<code class=\"docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code> 設定の最初のエントリ)。各ハッシャーのアルゴリズム名については <a class=\"reference internal\" href=\"#auth-included-hashers\"><span class=\"std std-ref\">Django に含まれるハッシャー</span></a> を参照してください。password 引数に <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を指定すると、使用できないパスワードが返されます (<a class=\"reference internal\" href=\"#django.contrib.auth.hashers.check_password\" title=\"django.contrib.auth.hashers.check_password\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">check_password()</span></code></a> では決して受け付けられません)。</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.is_password_usable\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_password_usable</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">encoded_password</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.is_password_usable\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードが <a class=\"reference internal\" href=\"/ja/5.1/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password\" title=\"django.contrib.auth.models.User.set_unusable_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">User.set_unusable_password()</span></code></a> の結果の場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> を返します。</p>\n</dd></dl>\n\n</section>\n<section id=\"module-django.contrib.auth.password_validation\">\n<span id=\"id3\"></span><span id=\"password-validation\"></span><h2>パスワードの妥当性検証<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.password_validation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>ユーザーは、良くないパスワードを選択することがあります。この問題を軽減するために、Djangoはプラガブルなパスワードの妥当性検証を提供しています。複数のパスワードの妥当性検証を同時に設定できます。いくつかのバリデータは Django に含まれていますが、自分で書くこともできます。</p>\n<p>各パスワードのバリデータは、ユーザーに要件の説明文を与え、指定されたパスワードの妥当性検証を行い、要件を満たしていない場合はエラーメッセージを返し、オプションでユーザのパスワードが変更されたときに通知するコールバックを定義します。バリデータは、動作を細かく指定するためのオプション設定を持つこともできます。</p>\n<p>妥当性検証は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> の設定で管理されます。設定のデフォルトは、空のリストになってます。これは、ひとつもバリデータが適用されていないことを意味しています。 <a class=\"reference internal\" href=\"/ja/5.1/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a> を使用して作られた新しいプロジェクトでは、バリデータのセットはデフォルトで有効になっています。</p>\n<p>デフォルトでは、バリデータはパスワードをリセットまたは変更するフォームと <a class=\"reference internal\" href=\"/ja/5.1/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> と <a class=\"reference internal\" href=\"/ja/5.1/ref/django-admin/#django-admin-changepassword\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">changepassword</span></code></a> 管理コマンドで使用されます。たとえば、 <code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects.create_user()</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">create_superuser()</span></code> のようなモデルレベルではバリデータは適用されません。なぜなら、このレベルで Django とやりとりするのはユーザ ではなく開発者であると想定しているからであり、また、モデルのバリデーションがモデル作成の一環として自動的に実行されるわけではないからです。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">注釈</p>\n<p>パスワードの妥当性検証は多くの脆弱なパスワードの形式が使用されることを防ぎます。しかしながら、パスワードが全てのバリデータを通過するという事実は、強力なパスワードであることを保証するわけではありません。最も先進的なパスワードのバリデータでさえ検出できない、パスワードを弱めうる多くの要素があります。</p>\n</aside>\n<section id=\"enabling-password-validation\">\n<h3>パスワードの妥当性検証を有効にする<a class=\"heading-anchor\" href=\"#enabling-password-validation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>パスワードの妥当性検証は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> で構成されます:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">AUTH_PASSWORD_VALIDATORS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.contrib.auth.password_validation.UserAttributeSimilarityValidator&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.contrib.auth.password_validation.MinimumLengthValidator&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;min_length&quot;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.contrib.auth.password_validation.CommonPasswordValidator&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;NAME&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.contrib.auth.password_validation.NumericPasswordValidator&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>本例では組み込みの4つ全てのバリデータを有効化します。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code> は、パスワードとユーザの属性との類似性をチェックします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">MinimumLengthValidator</span></code> は、パスワードが最小の長さを満たしているかをチェックします。このバリデータはカスタムオプションで構成されます。現在の設定では、最小長さは、デフォルトの8文字ではなく、9文字になっています。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code> は、一般的なパスワードのリストにそのパスワードが入っていないかをチェックします。デフォルトでは、組み込まれた20,000個のパスワードのリストと比較します。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code> は、パスワードが全体的に数値ではないかをチェックします。</p></li>\n</ul>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code> については、たとえばこの例ではデフォルトの設定を使用しています。 <code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code> には設定はありません。</p>\n<p>パスワードバリデーションのヘルプテキストとエラーは、常に <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> に記載されているソート順に返されます。</p>\n</section>\n<section id=\"included-validators\">\n<h3>Django に含まれるバリデータ<a class=\"heading-anchor\" href=\"#included-validators\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django には 4 つのバリデータがあります:</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.MinimumLengthValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">MinimumLengthValidator</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">min_length</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">8</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.MinimumLengthValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードが最小限の長さであることを検証します。最小の長さは <code class=\"docutils literal notranslate\"><span class=\"pre\">min_length</span></code> パラメータでカスタマイズできます。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">UserAttributeSimilarityValidator</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user_attributes</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DEFAULT_USER_ATTRIBUTES</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">max_similarity</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">0.7</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.UserAttributeSimilarityValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードがユーザの特定の属性と十分に異なることを検証します。</p>\n<p>パラメータ <code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code> は、比較するユーザー属性の名前のイテラブルでなければなりません。この引数が指定されない場合、デフォルトが使用されます。<code class=\"docutils literal notranslate\"><span class=\"pre\">'username',</span> <span class=\"pre\">'first_name',</span> <span class=\"pre\">'last_name',</span> <span class=\"pre\">'email'</span></code> です。存在しない属性は無視されます。</p>\n<p>パスワードの最大類似度は <code class=\"docutils literal notranslate\"><span class=\"pre\">max_similarity</span></code> パラメータで 0.1 から 1.0 の範囲で指定できます。これは <a class=\"reference external\" href=\"https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.quick_ratio\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">difflib.SequenceMatcher.quick_ratio()</span></code></a> の結果と比較されます。0.1の値を指定すると、 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code> と大幅に異なるパスワード以外は拒否され、1.0の値を指定すると、属性の値と同じパスワードのみが拒否されます。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.CommonPasswordValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">CommonPasswordValidator</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_list_path</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DEFAULT_PASSWORD_LIST_PATH</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.CommonPasswordValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードが一般的なパスワードでないことを検証します。これはパスワードを小文字に変換し(大文字小文字を区別しない比較を行うため)、 <a class=\"reference external\" href=\"https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce\">Royce Williams</a> によって作成された20,000の一般的なパスワードのリストと照合します。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">password_list_path</span></code> には一般的なパスワードのカスタムファイルのパスを指定できます。このファイルには1行につき1つの小文字のパスワードが含まれている必要があり、プレーンテキストまたはgzip圧縮されている必要があります。</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.NumericPasswordValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">NumericPasswordValidator</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.NumericPasswordValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードが数字のみでないことを確認します。</p>\n</dd></dl>\n\n</section>\n<section id=\"integrating-validation\">\n<h3>バリデーションの統合<a class=\"heading-anchor\" href=\"#integrating-validation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.password_validation</span></code> には、独自のフォームや他のコードから呼び出して パスワード認証を統合できる関数がいくつかあります。これは、たとえばパスワードの設定にカスタムフォームを使ったり、 パスワードの設定を許可する API 呼び出しがある場合に便利です。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.validate_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">validate_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.validate_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードを検証します。すべてのバリデータがパスワードを有効と判定した場合、 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を返します。1つ以上のバリデータがパスワードを拒否した場合、バリデータからのすべてのエラーメッセージと共に <a class=\"reference internal\" href=\"/ja/5.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code></a> を発生させます。</p>\n<p>もし <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> オブジェクトを指定しなかった場合、バリデータによってはバリデーションを実行できず、任意のパスワードを受け取ってしまう可能性があります。</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_changed\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_changed</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_changed\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パスワードが変更されたことをすべてのバリデータに通知します。これは、パスワードの再利用を防止するバリデータなどで使用します。パスワードの変更に成功したら、これを呼び出さなければなりません。</p>\n<p><a class=\"reference internal\" href=\"/ja/5.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> のサブクラスでは、パスワードフィールドは <a class=\"reference internal\" href=\"/ja/5.1/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser.set_password\" title=\"django.contrib.auth.models.AbstractBaseUser.set_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_password()</span></code></a> を呼び出すと &quot;dirty&quot; としてマークされ、ユーザが保存された後に <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed()</span></code> が呼び出されます。</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_validators_help_texts\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_validators_help_texts</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_validators_help_texts\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>すべてのバリデータのヘルプテキストの一覧を返します。これらは、パスワードの条件をユーザに説明するものです。</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_validators_help_text_html\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_validators_help_text_html</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_validators_help_text_html\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>すべてのヘルプテキストを <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;ul&gt;</span></code> で囲んだ HTML 文字列を返します。これはフォームにパスワードバリデーションを追加する際に便利です。フォームフィールドの <code class=\"docutils literal notranslate\"><span class=\"pre\">help_text</span></code> パラメータに直接出力を渡すことができるからです。</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.get_password_validators\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_password_validators</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">validator_config</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.get_password_validators\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>パラメータ <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code> に基づいてバリデータオブジェクトのセットを返します。デフォルトでは、すべての関数は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> で定義されたバリデータを使用しますが、この関数を別のバリデータセットで呼び出して、その結果を他の関数の <code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> パラメータに渡すことで、カスタムバリデータセットを代わりに使用できます。これは、たいていの場面で使用する典型的なバリデータセットがありながら、 特別な場面で独自のバリデータセットが必要になる場合に便利です。常に同じバリデータを使う場合は、この関数を使う必要はありません。 <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> の設定がデフォルトで使われるからです。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code> の構造は <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> の構造と同じです。この関数の戻り値は上記の関数の <code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> パラメータに渡すことができます。</p>\n</dd></dl>\n\n<p>これらの関数にパスワードが渡される場合は、ハッシュ化されたパスワードではなく、常に平文のパスワードでなければならないことに注意してください。</p>\n</section>\n<section id=\"writing-your-own-validator\">\n<h3>独自のバリデータを書く<a class=\"heading-anchor\" href=\"#writing-your-own-validator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django の組み込みバリデータでは不十分な場合、自分でパスワードバリデータ を書くことができます。バリデータはとても小さなインタフェースを持っています。2 つのメソッドを実装しなければなりません:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">validate(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">user=None)</span></code>: パスワードを検証します。パスワードが有効な場合は <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を返し、パスワードが無効な場合はエラーメッセージと共に <a class=\"reference internal\" href=\"/ja/5.1/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code></a> を発生させます。もし <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> であった場合、バリデータが実行できないので、 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> を返してエラーにならないようにしてください。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_help_text()</span></code>: ユーザに要件を説明するためのヘルプテキストを提供します。</p></li>\n</ul>\n<p>バリデータの <a class=\"reference internal\" href=\"/ja/5.1/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> の <code class=\"docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code> にあるすべての項目がコンストラクタに渡されます。コンストラクタの引数にはデフォルト値を指定します。</p>\n<p>以下は、1つのオプション設定を持つ基本的なバリデータの例です。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.exceptions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ValidationError</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils.translation</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">gettext</span> <span class=\"k\">as</span> <span class=\"n\">_</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MinimumLengthValidator</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">min_length</span><span class=\"o\">=</span><span class=\"mi\">8</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span> <span class=\"o\">=</span> <span class=\"n\">min_length</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">validate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">ValidationError</span><span class=\"p\">(</span>\n                <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;This password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span><span class=\"p\">),</span>\n                <span class=\"n\">code</span><span class=\"o\">=</span><span class=\"s2\">&quot;password_too_short&quot;</span><span class=\"p\">,</span>\n                <span class=\"n\">params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;min_length&quot;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">},</span>\n            <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_help_text</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">_</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;Your password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span>\n            <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s2\">&quot;min_length&quot;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">}</span>\n        <span class=\"p\">)</span>\n</code></pre></div>\n<p>パスワードの変更が成功した後に呼び出される <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed(password,</span> <span class=\"pre\">user=None</span></code>) を実装することもできます。これはたとえばパスワードの再利用を防ぐために使用できます。しかし、ユーザーの以前のパスワードを保存することにした場合、決して平文で保存してはいけません。</p>\n</section>\n</section>","rootId":"password-management-in-django","toc":[{"title":"Djangoのパスワード保存方法","anchor":"how-django-stores-passwords","children":[{"title":"Django で Argon2 を使う","anchor":"using-argon2-with-django","children":[]},{"title":"Django で bcrypt を使う","anchor":"using-bcrypt-with-django","children":[]},{"title":"Django で scrypt を使う","anchor":"using-scrypt-with-django","children":[]},{"title":"ソルトのエントロピーを増加させる","anchor":"increasing-the-salt-entropy","children":[]},{"title":"work factor を増やす","anchor":"increasing-the-work-factor","children":[{"title":"PBKDF2 と bcrypt","anchor":"pbkdf2-and-bcrypt","children":[]},{"title":"Argon2","anchor":"argon2","children":[]},{"title":"scrypt","anchor":"scrypt","children":[]}]},{"title":"パスワードのアップグレード","anchor":"password-upgrading","children":[]},{"title":"ログインを必要としないパスワードアップグレード","anchor":"password-upgrading-without-requiring-a-login","children":[]},{"title":"Django に含まれるハッシャー","anchor":"included-hashers","children":[]},{"title":"独自のハッシャーを書く","anchor":"writing-your-own-hasher","children":[]}]},{"title":"ユーザーのパスワードを手動で管理する","anchor":"module-django.contrib.auth.hashers","children":[]},{"title":"パスワードの妥当性検証","anchor":"module-django.contrib.auth.password_validation","children":[{"title":"パスワードの妥当性検証を有効にする","anchor":"enabling-password-validation","children":[]},{"title":"Django に含まれるバリデータ","anchor":"included-validators","children":[]},{"title":"バリデーションの統合","anchor":"integrating-validation","children":[]},{"title":"独自のバリデータを書く","anchor":"writing-your-own-validator","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/5.1/topics/"},{"docname":"topics/auth/index","title":"Django でのユーザー認証","url":"/ja/5.1/topics/auth/"}],"prev":{"docname":"topics/auth/default","title":"Djangoの認証システムを使用する","url":"/ja/5.1/topics/auth/default/"},"next":{"docname":"topics/auth/customizing","title":"Django の認証方法のカスタマイズ","url":"/ja/5.1/topics/auth/customizing/"},"formats":{"html":"/ja/5.1/topics/auth/passwords/","markdown":"/ja/5.1/topics/auth/passwords.md","json":"/ja/5.1/topics/auth/passwords.json"},"source":"https://github.com/django/django/blob/stable/5.1.x/docs/topics/auth/passwords.txt","official":"https://docs.djangoproject.com/ja/5.1/topics/auth/passwords/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}