{"title":"Pengelolaan sandi di Django","version":"6.0","locale":"id","docname":"topics/auth/passwords","url":"/id/6.0/topics/auth/passwords/","canonical":"https://djangodocs.dev/id/6.0/topics/auth/passwords/","summary":"Pengelolaan sandi adalah sesuatu yang harus secara umum tidak dibuat kembali tida perlu, dan Django berusaha menyediakan kumpulan aman dan fleksibel dari alat-alat…","html":"<h1>Pengelolaan sandi di 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>Pengelolaan sandi adalah sesuatu yang harus secara umum tidak dibuat kembali tida perlu, dan Django berusaha menyediakan kumpulan aman dan fleksibel dari alat-alat untuk mengelola sandi pengguna. Dokumen ini menggambarkan bagaimana Django menyimpan sandi, bagaimana campuran penyimpanan dapat dikonfigurasikan, dan beberapa peralatan untuk bekerja dengan sandi dicampur.</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">Lihat juga</p>\n<p>Meskipun pengguna mungkin menggunakan sandi kuat, penyerang mungkin dapat menguping pada hubungan mereka. Gunakan <a class=\"reference internal\" href=\"/id/6.0/topics/security/#security-recommendation-ssl\"><span class=\"std std-ref\">HTTPS</span></a> untuk menghindari mengirim sandi (atau data sensitif lain apapun) terhadap hubungan HTTP polos karena merekan akan menjadi rentan pada penciuman sandi.</p>\n</aside>\n<section id=\"how-django-stores-passwords\">\n<span id=\"auth-password-storage\"></span><h2>Bagaimana Django menyimpan sandi<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 menyediakan sistem penyimpanan sandi fleksibel dan menggunakan PBKDF2 secara awalan.</p>\n<p>Atribut <a class=\"reference internal\" href=\"/id/6.0/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> dari objek <a class=\"reference internal\" href=\"/id/6.0/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> adalah string dalam bentuk ini:</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>Those are the components used for storing a User's password, separated by the\ndollar-sign character and consist of: the hashing algorithm, the number of\nalgorithm iterations (work factor), the random salt, and the resulting password\nhash. The algorithm is one of a number of one-way hashing or password storage\nalgorithms Django can use; see below. Iterations describe the number of times\nthe algorithm is run over the hash. Salt is the random seed used and the hash\nis the result of the one-way function.</p>\n<p>Secara awalan, Django menggunakan algoritma <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/PBKDF2\">PBKDF2</a> dengan campuran SHA256, sebuah mekanisme perentangan sandi dianjurkan oleh <a class=\"reference external\" href=\"https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf\">NIST</a>. Ini harus cukup untuk kebanyakan pengguna: itu sangat aman, membutuhkan jumlah besar waktu untuk merusak.</p>\n<p>However, depending on your requirements, you may choose a different\nalgorithm, or even use a custom algorithm to match your specific\nsecurity situation. Again, most users shouldn't need to do this -- if\nyou're not sure, you probably don't. If you do, please read on:</p>\n<p>Django memilih algoritma untuk digunakan dengan berkonsultasi dengan pengaturan <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>. Ini adalah daftar kelas algoritma hashing yang didukung instalasi Django ini.</p>\n<p>Untuk menyimpan kata sandi, Django akan menggunakan hasher pertama di <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>. Untuk menyimpan kata sandi baru dengan algoritma berbeda, tempatkan algoritma pilihan anda terlebih dahulu di <a class=\"reference internal\" href=\"/id/6.0/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>Untuk memverifikasi kata sandi, Django akan menemukan hasher dalam daftar yang cocok dengan nama algoritma dalam kata sandi tersimpan. Jika kata sandi tersimpan menyebutkan algoritma yang tidak ditemukan di <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>, mencoba memverifikasinya akan memunculkan <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueError</span></code>.</p>\n<p>Nilai awal untuk <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> adalah:</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>Ini berarti bahwa Django akan menggunakan <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/PBKDF2\">PBKDF2</a> menyimpan semua sandi tetapi akan mendukung pemeriksaan sandi disimpan dengan PBKDF2SHA1, <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">argon2</a>, dan <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Bcrypt\">bcrypt</a>.</p>\n<p>Sedikit bagian selanjutnya menggambarkan sepasang cara umum pengguna tingkat lanjut mungkin ingin merubah pengaturan ini.</p>\n<section id=\"using-argon2-with-django\">\n<span id=\"argon2-usage\"></span><h3>Menggunakan Argon2 dengan 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> adalah pemenang Kompetisi Hashing Kata Sandi 2015, sebuah kompetisi terbuka yang diselenggarakan komunitas untuk memilih algoritma hashing generasi berikutnya. Ini dirancang agar tidak lebih mudah untuk menghitung pada perangkat keras khusus daripada menghitung pada CPU biasa. Varian awalan untuk hasher kata sandi Argon2 adalah Argon2id.</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> bukan awalan untuk Django karena itu membutuhkan pustaka pihak-ketiga. Juri Password Hashing Competition, bagaimanapun, menganjurkan penggunaan segera dari Argon2 daripada algoritma lain didukung oleh Django.</p>\n<p>Untuk menggunakan Argon2id sebagai algoritma penyimpanan awalan anda, lakukan hal berikut:</p>\n<ol class=\"arabic\">\n<li><p>Install the <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/argon2-cffi/\">argon2-cffi</a> package. 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\">pyproject.toml</span></code>).</p></li>\n<li><p>Rubah <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> pada daftar <code class=\"docutils literal notranslate\"><span class=\"pre\">Argon2PasswordHasher</span></code> pertama. Yaitu, di berkas pengaturan anda, anda telah taruh:</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>Jaga dan/atau tambah masukan apapun di daftar ini jika anda butuh Django untuk <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">upgrade passwords</span></a>.</p>\n</li>\n</ol>\n</section>\n<section id=\"using-bcrypt-with-django\">\n<span id=\"bcrypt-usage\"></span><h3>Menggunakan <code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt</span></code> dengan 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> adalah algoritma penyimpanan sandi terkenal yang khususnya dirancang untuk penyimpanan sandi jangka-panjang. Itu bukan awalan digunakan oleh Django sejak itu membutuhkan menggunakan pustaka pihak-ketiga, tetapi sejak banyak orang mungkin ingin menggunakan itu Django mendukung bcrypt dengan usaha minimal.</p>\n<p>Untuk menggunakan Bcrypt sebagai algoritma penyimpanan awalan anda, lakukan berikut:</p>\n<ol class=\"arabic\">\n<li><p>Install the <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/bcrypt/\">bcrypt</a> package. 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\">pyproject.toml</span></code>).</p></li>\n<li><p>Rubah <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> pada daftar <code class=\"docutils literal notranslate\"><span class=\"pre\">BCryptSHA256PasswordHasher</span></code> pertama. Yaitu, di berkas pengaturan anda, anda telah taruh:</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>Jaga dan/atau tambah masukan apapun di daftar ini jika anda butuh Django untuk <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">upgrade passwords</span></a>.</p>\n</li>\n</ol>\n<p>Yaitu -- sekarang Django memasang dengan menggunakan Bcrypt sebagai algoritma penyimpanan awalan.</p>\n</section>\n<section id=\"using-scrypt-with-django\">\n<span id=\"scrypt-usage\"></span><h3>Menggunakan <code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> dengan Django<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> mirip dengan PBKDF2 dan bcrypt dalam memanfaatkan sejumlah iterasi untuk memperlambat serangan brute-force. Namun, karena PBKDF2 dan bcrypt tidak membutuhkan banyak memori, penyerang dengan sumber daya yang cukup dapat melancarkan serangan paralel berskala besar untuk mempercepat proses penyerangan. <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> secara khusus dirancang untuk menggunakan lebih banyak memori dibandingkan dengan fungsi derivasi kunci berbasis kata sandi lainnya untuk membatasi jumlah paralelisme yang dapat digunakan penyerang, lihat <span class=\"target\" id=\"index-2\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7914.html\"><strong>RFC 7914</strong></a> untuk detail lebih lanjut.</p>\n<p>Untuk menggunakan <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> sebagai algoritma penyimpanan default anda, lakukan hal berikut:</p>\n<ol class=\"arabic\">\n<li><p>Ubah <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> untuk mencantumkan <code class=\"docutils literal notranslate\"><span class=\"pre\">ScryptPasswordHasher</span></code> terlebih dahulu. Yaitu, di berkas pengaturan Anda</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>Jaga dan/atau tambah masukan apapun di daftar ini jika anda butuh Django untuk <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">upgrade passwords</span></a>.</p>\n</li>\n</ol>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Catatan</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> membutuhkan OpenSSL 1.1+.</p>\n</aside>\n</section>\n<section id=\"increasing-the-salt-entropy\">\n<h3>Meningkatkan entropi garam<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>Sebagian besar hash kata sandi menyertakan garam bersama dengan hash kata sandinya untuk melindungi dari serangan tabel pelangi. Garam itu sendiri adalah nilai acak yang meningkatkan ukuran dan juga biaya tabel pelangi dan saat ini ditetapkan pada 128 bit dengan nilai <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> di <code class=\"docutils literal notranslate\"><span class=\"pre\">BasePasswordHasher</span></code>. Karena biaya komputasi dan penyimpanan menurun, nilai ini harus dinaikkan. Saat menerapkan hasher kata sandi anda sendiri, anda bebas untuk mengganti nilai ini untuk menggunakan tingkat entropi yang diinginkan untuk hash kata sandi anda. <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> diukur dalam bit.</p>\n<aside class=\"admonition-implementation-detail admonition\">\n<p class=\"admonition-title\">Rincian penerapan</p>\n<p>Karena metode penyimpanan nilai garam, nilai <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> secara efektif merupakan nilai minimum. Misalnya nilai 128 akan memberikan garam yang sebenarnya mengandung 131 bit entropi.</p>\n</aside>\n</section>\n<section id=\"increasing-the-work-factor\">\n<span id=\"increasing-password-algorithm-work-factor\"></span><h3>Meningkatkan faktor kerja<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 dan 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>Algoritme PBKDF2 dan bcrypt menggunakan sejumlah pengulangan atau putaran hashing. Ini sengaja memperlambat penyerang, membuat serangan terhadap kata sandi yang di-campur menjadi lebih sulit. Namun, dengan meningkatnya daya hitung, jumlah putaran perlu ditingkatkan. Kami telah memilih awalan yang masuk akal (dan akan meningkatkannya dengan setiap terbitan Django), tetapi anda mungkin ingin menyetelnya naik atau turun, tergantung pada kebutuhan keamanan anda dan kekuatan pemrosesan yang tersedia. Untuk melakukannya, anda akan mensubklasifikasikan algoritma yang sesuai dan mengganti parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> (gunakan parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> saat mensubklasifikasikan bcrypt hasher). Misalnya, untuk menambah jumlah pengulangan yang digunakan oleh algoritma awalan PBKDF2:</p>\n<ol class=\"arabic\">\n<li><p>Buat subkelas dari <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>Simpan ini disuatu tempat di proyek anda. Sebagai contoh, anda mungkin menaruh ini di sebuah berkas seperti <code class=\"docutils literal notranslate\"><span class=\"pre\">myproject/hashers.py</span></code>.</p>\n</li>\n<li><p>Tambah pencampur baru anda sebagai masukan pertama di <a class=\"reference internal\" href=\"/id/6.0/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>Itu dia -- sekarang pemasangan Django anda akan menggunakan perulangan lebih ketika itu menyimpan sandi menggunakan PBKDF2.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Catatan</p>\n<p>bcrypt <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> adalah faktor kerja logaritmik, mis. 12 putaran berarti pengulangan <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 memiliki atribut berikut yang dapat disesuaikan:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> mengendalikan sejumlah perulangan dalam campuran.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> mengendalikan ukuran memori yang harus digunakan selama perhitungan dari campuran.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> mengendalikan berapa banyak CPU perhitungan dari campuran dapat diparalelkan.</p></li>\n</ol>\n<p>Nilai-nilai awalan dari atribut ini mungkin baik untuk anda. Jika anda menentukan bahwa campuran sandi terlalu cepat atau terlalu lambat, anda dapat mengutik itu sebagai berikut:</p>\n<ol class=\"arabic simple\">\n<li><p>Pilih <code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> untuk menjadi angka dari thread anda dapat hemat menghitung campuran.</p></li>\n<li><p>Pilih <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> menjadi KiB dari memori anda dapat hemat.</p></li>\n<li><p>Menyesuaikan <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> dan ukuran waktu mencampur sebuah sandi yang diambil. Ambil sebuah <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> yang mengambil sebuah waktu yang dapat diterima untuk anda. Jika <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> disetel menjadi ` adalah tidak dapat diterima lambat, <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> lebih rendah.</p></li>\n</ol>\n<aside class=\"admonition-memory-cost-interpretation admonition\">\n<p class=\"admonition-title\">tafsiran <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code></p>\n<p>Kegunaan baris-perintah dan beberapa pustaka lain menafsirkan parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> berbeda dari nilai yang Django gunakan. Perubahan yang diberikan oleh <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> memiliki atribut berikut yang dapat disesuaikan:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">work_factor</span></code> controls the number of iterations within the hash and the\nsize of memory for computation (<em>N</em>). It must be a power of 2.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code> controls the internal block size (<em>r</em>), tuning the algorithm\nto memory latency.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> controls how many independent computations may run in\nparallel (<em>p</em>).</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> membatasi ukuran maksimum memori yang dapat digunakan selama perhitungan campuran. Awalan ke <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>, yang berarti batasan awalan dari pustaka OpenSSL.</p></li>\n</ol>\n<p>We've chosen reasonable defaults, but you may wish to tune it up or down,\ndepending on your security needs and available processing power and memory.</p>\n<aside class=\"admonition-estimating-memory-usage admonition\">\n<p class=\"admonition-title\">Memperkirakan penggunaan memori</p>\n<p>Persyaratan memori minimum <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> adalah</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>jadi anda mungkin perlu men-tweak <code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> saat mengubah nilai <code class=\"docutils literal notranslate\"><span class=\"pre\">work_factor</span></code> atau <code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code>.</p>\n<p>If the underlying implementation of <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> is fully multithreaded, the\nmemory requirement is multiplied by the <code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> value.</p>\n</aside>\n</section>\n</section>\n<section id=\"password-upgrading\">\n<span id=\"password-upgrades\"></span><h3>Peningkatan sandi<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>Ketika pengguna masuk, jika sandi mereka disimpan dengan apapun lain dari algoritma yang dipilih, Django akan secara otomatis meningkatkan algoritma ke satu yang dipilih. Ini berarti bahwa pemasangan lama dari Django akan mendapatkan otomatis lebih aman ketika pengguna masuk, dan itu juga berarti bahwa anda dapat berganti ke algoritma pentimpanan (dan lebih baik) baru ketika mereka dibuat.</p>\n<p>Namun, Django hanya dapat memutakhirkan kata sandi yang menggunakan algoritma yang disebutkan di <a class=\"reference internal\" href=\"/id/6.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>, jadi saat Anda memutakhirkan ke sistem baru anda harus memastikan untuk tidak pernah <em>menghapus</em> masukan dari daftar ini. Jika anda melakukannya, pengguna yang menggunakan algoritma yang tidak disebutkan tidak akan dapat meningkatkan versi. Kata sandi campuran akan diperbarui saat menambah (atau mengurangi) jumlah perulangan PBKDF2, putaran bcrypt, atau atribut argon2.</p>\n<p>Waspada bahwa jika semua sandi di basisdata anda tidak dikodekan di algoritma pencampur awalan, anda mungkin rentan pada serangan pewaktu pencacahan pengguna karena perbedaan diantara lamanya dari permintaan masuk untuk pengguna dengan sandi terkodekan di algoritma bukan-awalan dan lamanya dari permintaan masuk untuk pengguna tidak ada (yang menjalankan pencampur awalan). Anda mungkin dapat memperbaiki ini dengan <a class=\"reference internal\" href=\"#wrapping-password-hashers\"><span class=\"std std-ref\">upgrading older password hashes</span></a>.</p>\n</section>\n<section id=\"password-upgrading-without-requiring-a-login\">\n<span id=\"wrapping-password-hashers\"></span><h3>Meningkatkan sandi tanpa membutuhkan masuk<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>Jika anda memiliki basisdata yang sudah ada dengan campuran yang lebih lama dan lemah seperti MD5, anda mungkin ingin memutakhirkan sendiri campuran tersebut alih-alih menunggu pemutakhiran terjadi saat pengguna masuk (yang mungkin tidak akan pernah terjadi jika pengguna tidak kembali ke situs anda). Dalam hal ini, anda dapat menggunakan pencampur kata sandi &quot;terbungkus&quot;.</p>\n<p>Untuk contoh ini, kami akan memigrasi kumpulan campuran MD5 untuk menggunakan PBKDF2(MD5(kata sandi)) dan menambahkan pencampur kata sandi yang sesuai untuk memeriksa apakah pengguna memasukkan kata sandi yang benar saat masuk. Kami menganggap kami menggunakan model <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> bawaan dan bahwa proyek kami memiliki aplikasi <code class=\"docutils literal notranslate\"><span class=\"pre\">accounts</span></code>. Anda dapat merubah pola untuk bekerja dengan algoritma apa pun atau dengan model pengguna disesuaikan.</p>\n<p>Pertama, kami akan menambah penyesuaian pencampur:</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>Perpindahan data mungkin terlihat seperti:</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>Waspada bahwa perpindahan ini akan mengambil urutan dari beberapa menit untuk beberapa ribuan pengguna, tergantung pada kecepatan perangkat keras anda.</p>\n<p>Akhirya, kami akan menambah sebuah pengaturan <a class=\"reference internal\" href=\"/id/6.0/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>Sertakan pencampur lain apapun yang situs anda gunakan di daftar ini.</p>\n</section>\n<section id=\"included-hashers\">\n<span id=\"auth-included-hashers\"></span><h3>Disertakan pencampur<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>Daftar penuh dari pencampur disertakan di Django adalah:</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>Nama-nama algoritma sesuai adalah:</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>Menulis pencampur anda sendiri<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>Jika anda menulis pencampur sandi anda sendiri yang mengandung faktor kerja seperti sejumlah perulangan, anda harus menerapkan sebuah metode <code class=\"docutils literal notranslate\"><span class=\"pre\">harden_runtime(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">encoded)</span></code> untuk menjembatani celah waktu jalan diantara faktor kerja disokong di sandi <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> dan faktor kerja awalan dari pencampur. Ini mencegah serangan pewaktu pencacahan pengguna pada perbedaan diantara permintaan masuk untuk pengguna baru dengan sandi dikodekan di nomor terlama dari perulangan dan pengguna tidak ada (yang menjalankan nomor awalan pencampur bawaan dari perulangan).</p>\n<p>Mengambil PBKDF2 sebagai contoh, jika <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> mengandung 20,000 perputaran dan <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> awalan pencampur adalah 30,000, metode harus menjalankan <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> melalui perputaran 10,000 lain dari PBKDF2.</p>\n<p>Jika pencampur anda tidak mempunyai faktor kerja, terapkan metode sebagai no-op (<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>Manual mengelola sandi pengguna<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>Modul <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> menyediakan sekumpulan fungsi untuk membuat dan memvalidasi kata sandi campuran. Anda dapat menggunakannya secara terpisah dari model <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>Versi asinkron</em>: <code class=\"docutils literal notranslate\"><span class=\"pre\">acheck_password()</span></code></p>\n<p>If you'd like to manually authenticate a user by comparing a plaintext\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 mandatory arguments: the\nplaintext password to check, and the full value of a user's <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code>\nfield in the database to check against. It returns <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if they match,\n<code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> otherwise. Optionally, you can pass a callable <code class=\"docutils literal notranslate\"><span class=\"pre\">setter</span></code> that\ntakes the password and will be called when you need to regenerate it. You\ncan also pass <code class=\"docutils literal notranslate\"><span class=\"pre\">preferred</span></code> to change a hashing algorithm if you don't want\nto use the default (first entry of <code class=\"docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code> setting). See\n<a class=\"reference internal\" href=\"#auth-included-hashers\"><span class=\"std std-ref\">Disertakan pencampur</span></a> for the algorithm name of each hasher.</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 plaintext password (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\">Disertakan pencampur</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</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>Mengembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> jika sandi adalah hasil dari <a class=\"reference internal\" href=\"/id/6.0/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=\"id3\"></span><span id=\"password-validation\"></span><h2>Pengesahan sandi<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>Pengguna sering memilih kata sandi yang buruk. Untuk membantu mengurangi masalah ini, Django menawarkan validasi kata sandi yang dapat dicolokkan. Anda dapat mengonfigurasi beberapa validator kata sandi secara bersamaan. Beberapa validator disertakan dalam Django, tetapi anda juga dapat menulisnya sendiri.</p>\n<p>Each password validator must provide a help text to explain the requirements to\nthe user, validate a given password and return an error message if it does not\nmeet the requirements, and optionally define a callback to be notified when\nthe password for a user has been changed. Validators can also have optional\nsettings to fine tune their behavior.</p>\n<p>Validasi dikontrol oleh pengaturan <a class=\"reference internal\" href=\"/id/6.0/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>. Awalan untuk pengaturan adalah daftar kosong, yang berarti tidak ada validator yang diterapkan. Dalam proyek baru yang dibuat dengan cetakan awalan <a class=\"reference internal\" href=\"/id/6.0/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a>, sekumpulan validator diaktifkan secara awalan.</p>\n<p>Secara awalan, pengesah digunakan dalam formulir untuk menyetel kembali atau merubah sandi dan di perintah pengelolaan <a class=\"reference internal\" href=\"/id/6.0/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> dan <a class=\"reference internal\" href=\"/id/6.0/ref/django-admin/#django-admin-changepassword\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">changepassword</span></code></a>. Pengesah tidak diberlakukan pada tingkat model, sebagai contoh di User.objects.create_user()` dan <code class=\"docutils literal notranslate\"><span class=\"pre\">create_superuser()</span></code>, karena kami mengaggap bahwa pengembang, bukan pengguna, interaksi dengan Django pada tingkat itu dan juga karena pengesahan model tidak secara otomatis berjalan sebagai bagian dari membuat model.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Catatan</p>\n<p>Pengesah sandi dapat mencegah penggunaan dari banyak jenis dari sandi lemah. Bagaimanapun, fakta bahwa sandi melewatkan semua pengesah tidak menjami bahwa itu adalah sandi kuat. Ada banyak faktor yang dapat memperlemah sebuah sandi yang tidak dikenali oleh bahkan pengesah sandi paling tingkat lanjut.</p>\n</aside>\n<section id=\"enabling-password-validation\">\n<h3>Adakan pengesahan sandi<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>Pengesahan sandi dikonfigurasikan di pengaturan <a class=\"reference internal\" href=\"/id/6.0/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>Contoh ini mengadakan semua empat pengesah disertakan:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code>, yang memeriksa kemiripan diantara sandi dan sekumpulan dari atribut dari pengguna.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">MinimumLengthValidator</span></code>, yang memeriksa apakah kata sandi memenuhi panjang minimum. Validator ini dikonfigurasi dengan opsi khusus: sekarang membutuhkan panjang minimum sembilan karakter, bukan delapan karakter default.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>, yang memeriksa apakah kata sandi muncul dalam daftar kata sandi umum. Secara awalan, ini sebanding dengan daftar 20.000 kata sandi umum yang disertakan.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code>, yang memeriksa apakah sandi tidak sepenuhnya numerik.</p></li>\n</ul>\n<p>Untuk <code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code> dan <code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>, kami menggunakan pengaturan awalan dalam contoh ini. <code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code> tidak memiliki pengaturan.</p>\n<p>Teks bantuan dan kesalahan apapun dari pengesah sandi selalu dikembalikan agar mereka didaftarkan di <a class=\"reference internal\" href=\"/id/6.0/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<span id=\"included-password-validators\"></span><h3>Disertakan pengesah<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 menyertakan empat pengesah:</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>Memvalidasi bahwa kata sandi memiliki panjang minimum. Panjang minimum dapat disesuaikan dengan parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">min_length</span></code>.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.MinimumLengthValidator.get_error_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_error_message</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.MinimumLengthValidator.get_error_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>A hook for customizing the <code class=\"docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code> error message. Defaults\nto <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;This</span> <span class=\"pre\">password</span> <span class=\"pre\">is</span> <span class=\"pre\">too</span> <span class=\"pre\">short.</span> <span class=\"pre\">It</span> <span class=\"pre\">must</span> <span class=\"pre\">contain</span> <span class=\"pre\">at</span> <span class=\"pre\">least</span> <span class=\"pre\">&lt;min_length&gt;</span>\n<span class=\"pre\">characters.&quot;</span></code>.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.MinimumLengthValidator.get_help_text\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_help_text</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.MinimumLengthValidator.get_help_text\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>A hook for customizing the validator's help text. Defaults to <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Your</span>\n<span class=\"pre\">password</span> <span class=\"pre\">must</span> <span class=\"pre\">contain</span> <span class=\"pre\">at</span> <span class=\"pre\">least</span> <span class=\"pre\">&lt;min_length&gt;</span> <span class=\"pre\">characters.&quot;</span></code>.</p>\n</dd></dl>\n\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>Memvalidasi bahwa kata sandi cukup berbeda dari atribut tertentu pengguna.</p>\n<p>Parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code> harus berupa sebuah perulangan dari nama-namad dari atribut pengguna untuk dibandingkan. Jika argumen ini tidak disediakan, awalan adalah digunakan: <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>. Atribut-atribut yang tidak ada adalah diabaikan.</p>\n<p>Kesamaan kata sandi maksimum yang diizinkan dapat diatur pada skala 0,1 hingga 1,0 dengan parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">max_similarity</span></code>. Ini dibandingkan dengan hasil <a class=\"reference external\" href=\"https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.quick_ratio\" title=\"(di Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">difflib.SequenceMatcher.quick_ratio()</span></code></a>. Nilai 0,1 menolak kata sandi kecuali kata sandi tersebut sangat berbeda dari <code class=\"docutils literal notranslate\"><span class=\"pre\">atribut_pengguna</span></code>, sedangkan nilai 1,0 hanya menolak kata sandi yang identik dengan nilai atribut.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.UserAttributeSimilarityValidator.get_error_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_error_message</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.UserAttributeSimilarityValidator.get_error_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>A hook for customizing the <code class=\"docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code> error message. Defaults\nto <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;The</span> <span class=\"pre\">password</span> <span class=\"pre\">is</span> <span class=\"pre\">too</span> <span class=\"pre\">similar</span> <span class=\"pre\">to</span> <span class=\"pre\">the</span> <span class=\"pre\">&lt;user_attribute&gt;.&quot;</span></code>.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.UserAttributeSimilarityValidator.get_help_text\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_help_text</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.UserAttributeSimilarityValidator.get_help_text\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>A hook for customizing the validator's help text. Defaults to <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Your</span>\n<span class=\"pre\">password</span> <span class=\"pre\">can’t</span> <span class=\"pre\">be</span> <span class=\"pre\">too</span> <span class=\"pre\">similar</span> <span class=\"pre\">to</span> <span class=\"pre\">your</span> <span class=\"pre\">other</span> <span class=\"pre\">personal</span> <span class=\"pre\">information.&quot;</span></code>.</p>\n</dd></dl>\n\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 that 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 passwords created by <a class=\"reference external\" href=\"https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce\">Royce Williams</a>.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">password_list_path</span></code> dapat disetel ke jalur dari berkas penyesuaian dari sandi umum. Berkas ini harus mengandung sandi satu huruf kecil per baris dan mungkin berupa teks polos atau gzipped.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.CommonPasswordValidator.get_error_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_error_message</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.CommonPasswordValidator.get_error_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>A hook for customizing the <code class=\"docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code> error message. Defaults\nto <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;This</span> <span class=\"pre\">password</span> <span class=\"pre\">is</span> <span class=\"pre\">too</span> <span class=\"pre\">common.&quot;</span></code>.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.CommonPasswordValidator.get_help_text\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_help_text</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.CommonPasswordValidator.get_help_text\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>A hook for customizing the validator's help text. Defaults to <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Your</span>\n<span class=\"pre\">password</span> <span class=\"pre\">can’t</span> <span class=\"pre\">be</span> <span class=\"pre\">a</span> <span class=\"pre\">commonly</span> <span class=\"pre\">used</span> <span class=\"pre\">password.&quot;</span></code>.</p>\n</dd></dl>\n\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>Validasi bahwa kata sandi tidak sepenuhnya numerik.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.NumericPasswordValidator.get_error_message\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_error_message</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.NumericPasswordValidator.get_error_message\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>A hook for customizing the <code class=\"docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code> error message. Defaults\nto <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;This</span> <span class=\"pre\">password</span> <span class=\"pre\">is</span> <span class=\"pre\">entirely</span> <span class=\"pre\">numeric.&quot;</span></code>.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.NumericPasswordValidator.get_help_text\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_help_text</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.NumericPasswordValidator.get_help_text\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>A hook for customizing the validator's help text. Defaults to <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;Your</span>\n<span class=\"pre\">password</span> <span class=\"pre\">can’t</span> <span class=\"pre\">be</span> <span class=\"pre\">entirely</span> <span class=\"pre\">numeric.&quot;</span></code>.</p>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n<section id=\"integrating-validation\">\n<h3>Memadukan pengesahan<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>Ada sedikit fungsi di <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.password_validation</span></code> yang anda dapat memanggil dari formulir anda sendiri atau kode lain untuk memadukan pengesahan sandi. Ini dapat berguna jika anda menggunakan penyesuaian formulir untuk pengaturan sandi, atau jika anda mempunyai panggilan API yang mengizinkan sandi disetel, sebagai contoh.</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>Mengesahkan sebuah sandi. Jika semua pengesah menemukan sandi sah, mengembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>. Jika satu atau lebih pengesah menolak sandi, memunculkan sebuah <a class=\"reference internal\" href=\"/id/6.0/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> dengan semua pesan-pesan kesalahan dari pengesah.</p>\n<p>Obyek <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> adalah pilihan: jika itu tidak disediakan, beberapa pengesah mungkin tidak dapat melakukan pengesahan apapun dan akan menerima sandi apapun.</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>Menginformasikan semua pengesah yang sandi telah berubah. Ini dapat digunakan oleh pengesah seperti satu yang mencegah penggunaan kembali sandi. Ini harus dipanggil sekali sandi telah berhasil dirubah.</p>\n<p>Untuk subkelas-subkelas dari <a class=\"reference internal\" href=\"/id/6.0/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>, bidang sandi akan ditandai sebagai &quot;dirty&quot; ketika memanggil <a class=\"reference internal\" href=\"/id/6.0/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> yang memicu semua pada <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed()</span></code> setelah pengguna disimpan.</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>Mengembalikan daftar dari teks bantuan dari semua pengesah. Ini menjelaskan persyaratan sandi ke pengguna.</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>Mengembalikan sebuah string HTML dengan semua bantuan teks di sebuah <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;ul&gt;</span></code>. Ini sangat membantu ketika menambahkan pengesahan pada formulir, ketika anda dapat melewatkan keluaran secara langsung ke parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">help_text</span></code> dari bidang formulir.</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>Mengembalikan sekelompok obyek pengesah berdasarkan pada parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code>. Secara awalan, semua fungsi menggunakan pengesah ditentukan di <a class=\"reference internal\" href=\"/id/6.0/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>, tetapi dengan memanggil fungsi ini dengan alternatif kumpulan dari pengesah dan kemudian melewatkan hasil kedalam parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> dari fungsi lain, kumpulan penyesuaian anda dari pengesah akan digunakan sebagai gantinya. Ini sangat berguna ketika anda mempunyai kumpulan khusus dari pengesah untuk menggunakan kebanyakan skenario, tetapi juga mempunyai keadaan khusus yang membutuhkan penyesuaian kumpulan. Jika anda selalu menggunakan kumpulan sama dari pengesah, tidak perlu menggunakan fungsi ini, ketika konfigurasi dari <a class=\"reference internal\" href=\"/id/6.0/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> digunakan secara awalan.</p>\n<p>Struktur dari <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config``mirip</span> <span class=\"pre\">pada</span> <span class=\"pre\">struktur</span> <span class=\"pre\">dari</span> <span class=\"pre\">:setting:`AUTH_PASSWORD_VALIDATORS`.</span> <span class=\"pre\">Nilai</span> <span class=\"pre\">kembalian</span> <span class=\"pre\">dari</span> <span class=\"pre\">fungsi</span> <span class=\"pre\">ini</span> <span class=\"pre\">dapat</span> <span class=\"pre\">dilewatkan</span> <span class=\"pre\">kedalam</span> <span class=\"pre\">parameter</span> <span class=\"pre\">``password_validators</span></code> dari fungsi-fungsi terdaftar diatas.</p>\n</dd></dl>\n\n<p>Catat bahwa dimana sandi dilewatkan ke satu dari fungsi-fungsi ini, ini harus selalu sandi teks jelas - bukan sebuah sandi dicampur.</p>\n</section>\n<section id=\"writing-your-own-validator\">\n<h3>Menulis pengesah anda sendiri<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>Jika validator bawaan Django tidak cukup, anda dapat menulis validator kata sandi anda sendiri. Validator memiliki antarmuka yang cukup kecil. Mereka harus menerapkan dua metode:</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>: memvalidasi kata sandi. Kembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> jika kata sandi valid, atau naikkan <a class=\"reference internal\" href=\"/id/6.0/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> dengan pesan kesalahan jika kata sandi tidak valid. Anda harus dapat menangani <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> menjadi <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> - jika itu berarti validator anda tidak dapat berjalan, kembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> tanpa kesalahan.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_help_text()</span></code>: menyediakan teks bantuan untuk menjelaskan persyaratan ke pengguna.</p></li>\n</ul>\n<p>Barang apapun di <code class=\"docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code> di <a class=\"reference internal\" href=\"/id/6.0/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> untuk pengesah anda akan dilewatkan ke pembangun. Semua argumen pembangun harus memiliki nilai awalan.</p>\n<p>Ini adalah contoh dasar dari pengecekan, dengan satu pilihan pengaturan:</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>Anda dapat juga menerapkan <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed(password,</span> <span class=\"pre\">user=None</span></code>), yang akan dipanggil setelah perubahan sandi berhasil. Itu dapat digunakan untuk mencegah penggunaan kembali sandi, sebagai contoh. Bagaimanapun, jika anda memutuskan menyimpan sandi pengguna sebelumnya, anda harus tidak pernah melakukannya di pembersihan teks.</p>\n</section>\n</section>","rootId":"password-management-in-django","toc":[{"title":"Bagaimana Django menyimpan sandi","anchor":"how-django-stores-passwords","children":[{"title":"Menggunakan Argon2 dengan Django","anchor":"using-argon2-with-django","children":[]},{"title":"Menggunakan bcrypt dengan Django","anchor":"using-bcrypt-with-django","children":[]},{"title":"Menggunakan scrypt dengan Django","anchor":"using-scrypt-with-django","children":[]},{"title":"Meningkatkan entropi garam","anchor":"increasing-the-salt-entropy","children":[]},{"title":"Meningkatkan faktor kerja","anchor":"increasing-the-work-factor","children":[{"title":"PBKDF2 dan bcrypt","anchor":"pbkdf2-and-bcrypt","children":[]},{"title":"Argon2","anchor":"argon2","children":[]},{"title":"scrypt","anchor":"scrypt","children":[]}]},{"title":"Peningkatan sandi","anchor":"password-upgrading","children":[]},{"title":"Meningkatkan sandi tanpa membutuhkan masuk","anchor":"password-upgrading-without-requiring-a-login","children":[]},{"title":"Disertakan pencampur","anchor":"included-hashers","children":[]},{"title":"Menulis pencampur anda sendiri","anchor":"writing-your-own-hasher","children":[]}]},{"title":"Manual mengelola sandi pengguna","anchor":"module-django.contrib.auth.hashers","children":[]},{"title":"Pengesahan sandi","anchor":"module-django.contrib.auth.password_validation","children":[{"title":"Adakan pengesahan sandi","anchor":"enabling-password-validation","children":[]},{"title":"Disertakan pengesah","anchor":"included-validators","children":[]},{"title":"Memadukan pengesahan","anchor":"integrating-validation","children":[]},{"title":"Menulis pengesah anda sendiri","anchor":"writing-your-own-validator","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Menggunakan Django","url":"/id/6.0/topics/"},{"docname":"topics/auth/index","title":"Otentifikasi pengguna di Django","url":"/id/6.0/topics/auth/"}],"prev":{"docname":"topics/auth/default","title":"Menggunakan sistem pembuktian keaslian Django","url":"/id/6.0/topics/auth/default/"},"next":{"docname":"topics/auth/customizing","title":"Mengkostumisasi autentikasi di Django","url":"/id/6.0/topics/auth/customizing/"},"formats":{"html":"/id/6.0/topics/auth/passwords/","markdown":"/id/6.0/topics/auth/passwords.md","json":"/id/6.0/topics/auth/passwords.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/auth/passwords.txt","official":"https://docs.djangoproject.com/id/6.0/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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}