{"title":"Djangoにおけるパスワード管理","version":"3.1","locale":"ja","docname":"topics/auth/passwords","url":"/ja/3.1/topics/auth/passwords/","canonical":"https://djangodocs.dev/ja/3.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接続で送信されないように、:ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>HTTPS &lt;security-recommendation-ssl&gt;`を使用してください。なぜなら、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>The <a class=\"reference internal\" href=\"/ja/3.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> attribute of a\n<a class=\"reference internal\" href=\"/ja/3.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> object is a string in this format:</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>&lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;$&lt;hash&gt;\n</code></pre></div>\n<p>これらはユーザーのパスワードを保存するためのコンポーネントで、ハッシュアルゴリズム、アルゴリズムのイテレーション回数（ワークファクター）、ランダムなソルト、そして結果のパスワードハッシュをドル記号($)で区切ったものです。このアルゴリズムは、Djangoが使用できる数多くの一方向ハッシュ、またはパスワード保存アルゴリズム（下記参照）の一つです。イテレーションはハッシュに対してアルゴリズムが実行された回数を表します。ソルトは使用されたランダムシードで、ハッシュは一方向ハッシュ関数の実行結果です。</p>\n<p>デフォルトでは、DjangoはNISTが推奨するパスワードストレッチングメカニズムであるPBKDF2アルゴリズムとSHA256ハッシュを使用します。これはほとんどのユーザーに十分有効なはずです。非常に安全で、クラックするのに膨大な計算時間を必要とします。</p>\n<p>ただし、要件に応じて、異なるアルゴリズムを使用することも、一部のセキュリティ状況に合わせてカスタムアルゴリズムを使用することもできます。繰り返しますが、ほとんどのユーザーはこれを行う必要はありません。よくわからない場合、おそらくそうしないほうが良いです。もしそうする場合は、こちらをお読みください:</p>\n<p>Djangoは <a class=\"reference internal\" href=\"/ja/3.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インストールがサポートするハッシュアルゴリズムクラスのリストです。このリストの最初のエントリ（つまり、 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.PASSWORD_HASHERS[0]</span></code> ）がパスワードの保存に使用され、他の全てのエントリは、既に存在するパスワードの検証に使用できる有効性検証ハッシャです。つまり、他のアルゴリズムを使用したい場合は <a class=\"reference internal\" href=\"/ja/3.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>デフォルトでの <a class=\"reference internal\" href=\"/ja/3.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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>これは、DjangoはPBKDF2_を使用して全てのパスワードを保存しますが、PBKDF2SHA1、<a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">argon2</a>、およびbcrypt_で保存されたパスワードのチェックもサポートすることを意味しています。</p>\n<p>次のいくつかのセクションでは、高度なユーザーがこの設定を変更するための一般的な方法について説明します。</p>\n<section id=\"using-argon2-with-django\">\n<span id=\"argon2-usage\"></span><h3>Using Argon2 with Django<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> is the winner of the 2015 <a class=\"reference external\" href=\"https://password-hashing.net\">Password Hashing Competition</a>, a community\norganized open competition to select a next generation hashing algorithm. It's\ndesigned not to be easier to compute on custom hardware than it is to compute\non an ordinary CPU.</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> is not the default for Django because it requires a third-party\nlibrary. The Password Hashing Competition panel, however, recommends immediate\nuse of Argon2 rather than the other algorithms supported by Django.</p>\n<p>To use Argon2 as your default storage algorithm, do the following:</p>\n<ol class=\"arabic\">\n<li><p>Install the <a class=\"reference external\" href=\"https://pypi.org/project/argon2_cffi/\">argon2-cffi library</a>.  This can be done by running\n<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>, which is equivalent to\n<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> (along with any version requirement\nfrom Django's <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.cfg</span></code>).</p></li>\n<li><p>Modify <a class=\"reference internal\" href=\"/ja/3.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> to list <code class=\"docutils literal notranslate\"><span class=\"pre\">Argon2PasswordHasher</span></code> first.\nThat is, in your settings file, you'd put:</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=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Keep and/or add any entries in this list if you need Django to <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">upgrade\npasswords</span></a>.</p>\n</li>\n</ol>\n</section>\n<section id=\"using-bcrypt-with-django\">\n<span id=\"bcrypt-usage\"></span><h3>Using <code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt</span></code> with Django<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> is a popular password storage algorithm that's specifically designed\nfor long-term password storage. It's not the default used by Django since it\nrequires the use of third-party libraries, but since many people may want to\nuse it Django supports bcrypt with minimal effort.</p>\n<p>To use Bcrypt as your default storage algorithm, do the following:</p>\n<ol class=\"arabic\">\n<li><p>Install the <a class=\"reference external\" href=\"https://pypi.org/project/bcrypt/\">bcrypt library</a>. This can be done by running\n<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>, which is equivalent to\n<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> (along with any version requirement from\nDjango's <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.cfg</span></code>).</p></li>\n<li><p>Modify <a class=\"reference internal\" href=\"/ja/3.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> to list <code class=\"docutils literal notranslate\"><span class=\"pre\">BCryptSHA256PasswordHasher</span></code>\nfirst. That is, in your settings file, you'd put:</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=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Keep and/or add any entries in this list if you need Django to <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">upgrade\npasswords</span></a>.</p>\n</li>\n</ol>\n<p>That's it -- now your Django install will use Bcrypt as the default storage\nalgorithm.</p>\n</section>\n<section id=\"increasing-the-work-factor\">\n<span id=\"increasing-password-algorithm-work-factor\"></span><h3>Increasing the 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 and 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>The PBKDF2 and bcrypt algorithms use a number of iterations or rounds of\nhashing. This deliberately slows down attackers, making attacks against hashed\npasswords harder. However, as computing power increases, the number of\niterations needs to be increased. We've chosen a reasonable default (and will\nincrease it with each release of Django), but you may wish to tune it up or\ndown, depending on your security needs and available processing power. To do so,\nyou'll subclass the appropriate algorithm and override the <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code>\nparameters. For example, to increase the number of iterations used by the\ndefault PBKDF2 algorithm:</p>\n<ol class=\"arabic\">\n<li><p>Create a subclass of <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<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    <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>Save this somewhere in your project. For example, you might put this in\na file like <code class=\"docutils literal notranslate\"><span class=\"pre\">myproject/hashers.py</span></code>.</p>\n</li>\n<li><p>Add your new hasher as the first entry in <a class=\"reference internal\" href=\"/ja/3.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=\"s1\">&#39;myproject.hashers.MyPBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ol>\n<p>That's it -- now your Django install will use more iterations when it\nstores passwords using PBKDF2.</p>\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 has three attributes that can be customized:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> controls the number of iterations within the hash.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> controls the size of memory that must be used during the\ncomputation of the hash.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> controls how many CPUs the computation of the hash can be\nparallelized on.</p></li>\n</ol>\n<p>The default values of these attributes are probably fine for you. If you\ndetermine that the password hash is too fast or too slow, you can tweak it as\nfollows:</p>\n<ol class=\"arabic simple\">\n<li><p>Choose <code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> to be the number of threads you can\nspare computing the hash.</p></li>\n<li><p>Choose <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> to be the KiB of memory you can spare.</p></li>\n<li><p>Adjust <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> and measure the time hashing a password takes.\nPick a <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> that takes an acceptable time for you.\nIf <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> set to 1 is unacceptably slow, lower <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> interpretation</p>\n<p>The argon2 command-line utility and some other libraries interpret the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> parameter differently from the value that Django uses. The\nconversion is given by <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>\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>However, Django can only upgrade passwords that use algorithms mentioned in\n<a class=\"reference internal\" href=\"/ja/3.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>, so as you upgrade to new systems you should make\nsure never to <em>remove</em> entries from this list. If you do, users using\nunmentioned algorithms won't be able to upgrade. Hashed passwords will be\nupdated when increasing (or decreasing) the number of PBKDF2 iterations, bcrypt\nrounds, or argon2 attributes.</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>Password upgrading without requiring a login<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>If you have an existing database with an older, weak hash such as MD5 or SHA1,\nyou might want to upgrade those hashes yourself instead of waiting for the\nupgrade to happen when a user logs in (which may never happen if a user doesn't\nreturn to your site). In this case, you can use a &quot;wrapped&quot; password hasher.</p>\n<p>For this example, we'll migrate a collection of SHA1 hashes to use\nPBKDF2(SHA1(password)) and add the corresponding password hasher for checking\nif a user entered the correct password on login. We assume we're using the\nbuilt-in <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> model and that our project has an <code class=\"docutils literal notranslate\"><span class=\"pre\">accounts</span></code> app. You can\nmodify the pattern to work with any algorithm or with a custom user model.</p>\n<p>First, we'll add the custom hasher:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">accounts/hashers.py</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> <span class=\"n\">SHA1PasswordHasher</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\">PBKDF2WrappedSHA1PasswordHasher</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=\"s1\">&#39;pbkdf2_wrapped_sha1&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">encode_sha1_hash</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">sha1_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\">sha1_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\">sha1_hash</span> <span class=\"o\">=</span> <span class=\"n\">SHA1PasswordHasher</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=\"s1\">&#39;$&#39;</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_sha1_hash</span><span class=\"p\">(</span><span class=\"n\">sha1_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>The data migration might look something like:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">accounts/migrations/0002_migrate_sha1_passwords.py</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\">PBKDF2WrappedSHA1PasswordHasher</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=\"s1\">&#39;auth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;User&#39;</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=\"s1\">&#39;sha1$&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">hasher</span> <span class=\"o\">=</span> <span class=\"n\">PBKDF2WrappedSHA1PasswordHasher</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\">sha1_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=\"s1\">&#39;$&#39;</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_sha1_hash</span><span class=\"p\">(</span><span class=\"n\">sha1_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=\"s1\">&#39;password&#39;</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\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;accounts&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_initial&#39;</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=\"s1\">&#39;auth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;####_migration_name&#39;</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>Be aware that this migration will take on the order of several minutes for\nseveral thousand users, depending on the speed of your hardware.</p>\n<p>Finally, we'll add a <a class=\"reference internal\" href=\"/ja/3.1/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> setting:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">mysite/settings.py</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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;accounts.hashers.PBKDF2WrappedSHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>Include any other hashers that your site uses in this list.</p>\n</section>\n<section id=\"included-hashers\">\n<span id=\"auth-included-hashers\"></span><h3>Included hashers<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>The full list of hashers included in Django is:</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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.MD5PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.UnsaltedMD5PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.CryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>The corresponding algorithm names are:</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\">sha1</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">md5</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">unsalted_sha1</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">unsalted_md5</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">crypt</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>Writing your own hasher<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>If you write your own password hasher that contains a work factor such as a\nnumber of iterations, you should implement a\n<code class=\"docutils literal notranslate\"><span class=\"pre\">harden_runtime(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">encoded)</span></code> method to bridge the runtime gap\nbetween the work factor supplied in the <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> password and the default\nwork factor of the hasher. This prevents a user enumeration timing attack due\nto  difference between a login request for a user with a password encoded in an\nolder number of iterations and a nonexistent user (which runs the default\nhasher's default number of iterations).</p>\n<p>Taking PBKDF2 as example, if <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> contains 20,000 iterations and the\nhasher's default <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> is 30,000, the method should run <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code>\nthrough another 10,000 iterations of PBKDF2.</p>\n<p>If your hasher doesn't have a work factor, implement the method as a no-op\n(<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>Manually managing a user's password<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>The <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> module provides a set of functions\nto create and validate hashed passwords. You can use them independently\nfrom the <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> model.</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><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><p>If you'd like to manually authenticate a user by comparing a plain-text\npassword to the hashed password in the database, use the convenience\nfunction <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>. It takes two arguments: the plain-text\npassword to check, and the full value of a user's <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> field in the\ndatabase to check against, and returns <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if they match, <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>\notherwise.</p>\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>Creates a hashed password in the format used by this application. It takes\none mandatory argument: the password in plain-text (string or bytes).\nOptionally, you can provide a salt and a hashing algorithm to use, if you\ndon't want to use the defaults (first entry of <code class=\"docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code>\nsetting). See <a class=\"reference internal\" href=\"#auth-included-hashers\"><span class=\"std std-ref\">Included hashers</span></a> for the algorithm name of each\nhasher. If the password argument is <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>, an unusable password is\nreturned (one that will never be accepted by <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<aside class=\"version-note version-changed\" data-version=\"3.1\">\n<p class=\"version-note-title\">Changed in Django 3.1</p><p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> parameter must be a string or bytes if not <code class=\"docutils literal notranslate\"><span class=\"pre\">None</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.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>Returns <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> if the password is a result of\n<a class=\"reference internal\" href=\"/ja/3.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>.</p>\n</dd></dl>\n\n</section>\n<section id=\"module-django.contrib.auth.password_validation\">\n<span id=\"id2\"></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>Users often choose poor passwords. To help mitigate this problem, Django\noffers pluggable password validation. You can configure multiple password\nvalidators at the same time. A few validators are included in Django, but you\ncan write your own as well.</p>\n<p>各パスワードのバリデータは、ユーザーに要件の説明文を与え、指定されたパスワードの妥当性検証を行い、要件を満たしていない場合はエラーメッセージを返し、必要に応じて設定されたパスワードを受信します。バリデータは、それらの挙動を微調整するオプション設定を持つこともできます。</p>\n<p>Validation is controlled by the <a class=\"reference internal\" href=\"/ja/3.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> setting.\nThe default for the setting is an empty list, which means no validators are\napplied. In new projects created with the default <a class=\"reference internal\" href=\"/ja/3.1/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a>\ntemplate, a set of validators is enabled by default.</p>\n<p>By default, validators are used in the forms to reset or change passwords and\nin the <a class=\"reference internal\" href=\"/ja/3.1/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> and <a class=\"reference internal\" href=\"/ja/3.1/ref/django-admin/#django-admin-changepassword\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">changepassword</span></code></a> management\ncommands. Validators aren't applied at the model level, for example in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects.create_user()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">create_superuser()</span></code>, because we assume\nthat developers, not users, interact with Django at that level and also because\nmodel validation doesn't automatically run as part of creating models.</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/3.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=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.UserAttributeSimilarityValidator&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.MinimumLengthValidator&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;min_length&#39;</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=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.CommonPasswordValidator&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.NumericPasswordValidator&#39;</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><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>UserAttributeSimilarityValidator``は、パスワードとユーザの属性との類似性をチェックします。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">MinimumLengthValidator</span></code>, which checks whether the password meets a minimum\nlength. This validator is configured with a custom option: it now requires\nthe minimum length to be nine characters, instead of the default eight.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>, which checks whether the password occurs in a\nlist of common passwords. By default, it compares to an included list of\n20,000 common passwords.</p></li>\n<li><p><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>NumericPasswordValidator``は、パスワードが全体的に数値ではないかをチェックします。</p></li>\n</ul>\n<p>For <code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>,\nwe're using the default settings in this example. <code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code>\nhas no settings.</p>\n<p>The help texts and any errors from password validators are always returned in\nthe order they are listed in <a class=\"reference internal\" href=\"/ja/3.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>Included validators<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 includes four validators:</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>Validates whether the password meets a minimum length.\nThe minimum length can be customized with the <code class=\"docutils literal notranslate\"><span class=\"pre\">min_length</span></code> parameter.</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>Validates whether the password is sufficiently different from certain\nattributes of the user.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code> parameter should be an iterable of names of user\nattributes to compare to. If this argument is not provided, the default\nis used: <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>.\nAttributes that don't exist are ignored.</p>\n<p>The minimum similarity of a rejected password can be set on a scale of 0 to\n1 with the <code class=\"docutils literal notranslate\"><span class=\"pre\">max_similarity</span></code> parameter. A setting of 0 rejects all\npasswords, whereas a setting of 1 rejects only passwords that are identical\nto an attribute's value.</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>Validates whether the password is not a common password. This converts the\npassword to lowercase (to do a case-insensitive comparison) and checks it\nagainst a list of 20,000 common password created by <a class=\"reference external\" href=\"https://gist.github.com/roycewilliams/281ce539915a947a23db17137d91aeb7\">Royce Williams</a>.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">password_list_path</span></code> can be set to the path of a custom file of\ncommon passwords. This file should contain one lowercase password per line\nand may be plain text or gzipped.</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>Validates whether the password is not entirely numeric.</p>\n</dd></dl>\n\n</section>\n<section id=\"integrating-validation\">\n<h3>Integrating validation<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>There are a few functions in <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.password_validation</span></code> that\nyou can call from your own forms or other code to integrate password\nvalidation. This can be useful if you use custom forms for password setting,\nor if you have API calls that allow passwords to be set, for example.</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>Validates a password. If all validators find the password valid, returns\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>. If one or more validators reject the password, raises a\n<a class=\"reference internal\" href=\"/ja/3.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> with all the error messages\nfrom the validators.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> object is optional: if it's not provided, some validators may\nnot be able to perform any validation and will accept any password.</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>Informs all validators that the password has been changed. This can be used\nby validators such as one that prevents password reuse. This should be\ncalled once the password has been successfully changed.</p>\n<p>For subclasses of <a class=\"reference internal\" href=\"/ja/3.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>,\nthe password field will be marked as &quot;dirty&quot; when calling\n<a class=\"reference internal\" href=\"/ja/3.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> which\ntriggers a call to <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed()</span></code> after the user is saved.</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>Returns a list of the help texts of all validators. These explain the\npassword requirements to the user.</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>Returns an HTML string with all help texts in an <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;ul&gt;</span></code>. This is\nhelpful when adding password validation to forms, as you can pass the\noutput directly to the <code class=\"docutils literal notranslate\"><span class=\"pre\">help_text</span></code> parameter of a form field.</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>Returns a set of validator objects based on the <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code>\nparameter. By default, all functions use the validators defined in\n<a class=\"reference internal\" href=\"/ja/3.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>, but by calling this function with an\nalternate set of validators and then passing the result into the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> parameter of the other functions, your custom set\nof validators will be used instead. This is useful when you have a typical\nset of validators to use for most scenarios, but also have a special\nsituation that requires a custom set. If you always use the same set\nof validators, there is no need to use this function, as the configuration\nfrom <a class=\"reference internal\" href=\"/ja/3.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> is used by default.</p>\n<p>The structure of <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code> is identical to the\nstructure of <a class=\"reference internal\" href=\"/ja/3.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>. The return value of\nthis function can be passed into the <code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> parameter\nof the functions listed above.</p>\n</dd></dl>\n\n<p>Note that where the password is passed to one of these functions, this should\nalways be the clear text password - not a hashed password.</p>\n</section>\n<section id=\"writing-your-own-validator\">\n<h3>Writing your own validator<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>If Django's built-in validators are not sufficient, you can write your own\npassword validators. Validators have a fairly small interface. They must\nimplement two methods:</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>: validate a password. Return\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> if the password is valid, or raise a\n<a class=\"reference internal\" href=\"/ja/3.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> with an error message if the\npassword is not valid. You must be able to deal with <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> being\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> - if that means your validator can't run, return <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> for no\nerror.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_help_text()</span></code>: provide a help text to explain the requirements to\nthe user.</p></li>\n</ul>\n<p>Any items in the <code class=\"docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code> in <a class=\"reference internal\" href=\"/ja/3.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> for your\nvalidator will be passed to the constructor. All constructor arguments should\nhave a default value.</p>\n<p>Here's a basic example of a validator, with one optional setting:</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<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=\"s1\">&#39;password_too_short&#39;</span><span class=\"p\">,</span>\n                <span class=\"n\">params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;min_length&#39;</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=\"s1\">&#39;min_length&#39;</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>You can also implement <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed(password,</span> <span class=\"pre\">user=None</span></code>), which will\nbe called after a successful password change. That can be used to prevent\npassword reuse, for example. However, if you decide to store a user's previous\npasswords, you should never do so in clear text.</p>\n</section>\n</section>","rootId":"password-management-in-django","toc":[{"title":"Djangoのパスワード保存方法","anchor":"how-django-stores-passwords","children":[{"title":"Using Argon2 with Django","anchor":"using-argon2-with-django","children":[]},{"title":"Using bcrypt with Django","anchor":"using-bcrypt-with-django","children":[]},{"title":"Increasing the work factor","anchor":"increasing-the-work-factor","children":[{"title":"PBKDF2 and bcrypt","anchor":"pbkdf2-and-bcrypt","children":[]},{"title":"Argon2","anchor":"argon2","children":[]}]},{"title":"パスワードの更新","anchor":"password-upgrading","children":[]},{"title":"Password upgrading without requiring a login","anchor":"password-upgrading-without-requiring-a-login","children":[]},{"title":"Included hashers","anchor":"included-hashers","children":[]},{"title":"Writing your own hasher","anchor":"writing-your-own-hasher","children":[]}]},{"title":"Manually managing a user's password","anchor":"module-django.contrib.auth.hashers","children":[]},{"title":"パスワードの妥当性検証","anchor":"module-django.contrib.auth.password_validation","children":[{"title":"パスワードの妥当性検証を有効にする","anchor":"enabling-password-validation","children":[]},{"title":"Included validators","anchor":"included-validators","children":[]},{"title":"Integrating validation","anchor":"integrating-validation","children":[]},{"title":"Writing your own validator","anchor":"writing-your-own-validator","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/3.1/topics/"},{"docname":"topics/auth/index","title":"Django でのユーザー認証","url":"/ja/3.1/topics/auth/"}],"prev":{"docname":"topics/auth/default","title":"Djangoの認証システムを使用する","url":"/ja/3.1/topics/auth/default/"},"next":{"docname":"topics/auth/customizing","title":"Django の認証方法のカスタマイズ","url":"/ja/3.1/topics/auth/customizing/"},"formats":{"html":"/ja/3.1/topics/auth/passwords/","markdown":"/ja/3.1/topics/auth/passwords.md","json":"/ja/3.1/topics/auth/passwords.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/topics/auth/passwords.txt","official":"https://docs.djangoproject.com/ja/3.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","pt-br","ko","es","el","pl"]}