{"title":"Pengelolaan sandi di Django","version":"3.2","locale":"id","docname":"topics/auth/passwords","url":"/id/3.2/topics/auth/passwords/","canonical":"https://djangodocs.dev/id/3.2/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/3.2/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/3.2/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 sebuah obyek <a class=\"reference internal\" href=\"/id/3.2/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 sebuah string di bentuk ini:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code>&lt;algorithm&gt;$&lt;iterations&gt;$&lt;salt&gt;$&lt;hash&gt;\n</code></pre></div>\n<p>Mereka adalah komponen digunakan untuk menyimpan sandi User, dipisahkan oleh karakter dolar dan terdiri dari campuran algoritma, sejumlah perulangan algoritma (faktor kerja), garam acak, dan menghasilkan campuran sandi. Algoritma adalah satu dari sejumlah dari campuran satu-cara atau algoritma penyimpanan sandi Django dapat digunakan, lihat dibawah. Perulangan menggambarkan sejumlah kali algoritma berjalan terhadap campuran. Garam adalah benih acak digunakan dan campuran adalah hasil dari fungsi satu-cara.</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>Bagaimapun, tergantung pada persyaratan anda, anda mungkin memilih algoritma berbeda, atau bahkan menggunakan penyesuaian algoritma untuk mencocokkan keadaan keamanan khusus. Kembali, kebanyakan pengguna tidak butuh melakukan ini -- jika anda tidak yakin, anda mungkin tidak. Jika anda melakukan, harap membaca:</p>\n<p>Django memilih algoritma untuk digunakan dengan berkonsultasi pengaturan <a class=\"reference internal\" href=\"/id/3.2/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 dari campuran kelas-kelas algoritma yang mendukung pemasangan Django ini. Masukan pertama di daftar (yaitu, <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.PASSWORD_HASHERS[0]</span></code>) akan digunakan menyimpan sandi, dan semua masukan lain adalah pencampur sah yang dapat digunakan memeriksa sandi yang ada. Ini berarti bahwa anda ingin menggunakan algoritma berbeda, anda akan butuh merubah <a class=\"reference internal\" href=\"/id/3.2/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> ke daftar anda pertama algoritma dipilih di daftar.</p>\n<p>Nilai awal untuk <a class=\"reference internal\" href=\"/id/3.2/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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>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 dari <a class=\"reference external\" href=\"https://www.password-hashing.net/\">Password Hashing Competition</a> 2015, sebuah komunitas mengorganisasikan pertandingan terbuka untuk memilih algoritma campuran generasi selanjutnya. Itu dirancang tidak mudah dihitung pada perangkat keras penyesuaian daripada itu dihitung pada CPU biasa.</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 Argon2 sebagai algoritma penyimpanan awalan anda, lakukan berikut:</p>\n<ol class=\"arabic\">\n<li><p>Install the <a class=\"reference external\" href=\"https://pypi.org/project/argon2-cffi/\">argon2-cffi library</a>.  This can be done by running\n<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">django[argon2]</span></code>, which is equivalent to\n<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">argon2-cffi</span></code> (along with any version requirement\nfrom Django's <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.cfg</span></code>).</p></li>\n<li><p>Rubah <a class=\"reference internal\" href=\"/id/3.2/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=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>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=\"reference external\" href=\"https://pypi.org/project/bcrypt/\">bcrypt library</a>. This can be done by running\n<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">django[bcrypt]</span></code>, which is equivalent to\n<code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">-m</span> <span class=\"pre\">pip</span> <span class=\"pre\">install</span> <span class=\"pre\">bcrypt</span></code> (along with any version requirement from\nDjango's <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.cfg</span></code>).</p></li>\n<li><p>Rubah <a class=\"reference internal\" href=\"/id/3.2/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=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>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=\"increasing-the-salt-entropy\">\n<h3>Increasing the salt entropy<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<aside class=\"version-note version-added\" data-version=\"3.2\">\n<p class=\"version-note-title\">New in Django 3.2</p></aside>\n<p>Most password hashes include a salt along with their password hash in order to\nprotect against rainbow table attacks. The salt itself is a random value which\nincreases the size and thus the cost of the rainbow table and is currently set\nat 128 bits with the <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code> value in the <code class=\"docutils literal notranslate\"><span class=\"pre\">BasePasswordHasher</span></code>. As\ncomputing and storage costs decrease this value should be raised. When\nimplementing your own password hasher you are free to override this value in\norder to use a desired entropy level for your password hashes. <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code>\nis measured in bits.</p>\n<aside class=\"admonition-implementation-detail admonition\">\n<p class=\"admonition-title\">Rincian penerapan</p>\n<p>Due to the method in which salt values are stored the <code class=\"docutils literal notranslate\"><span class=\"pre\">salt_entropy</span></code>\nvalue is effectively a minimum value. For instance a value of 128 would\nprovide a salt which would actually contain 131 bits of entropy.</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>Algoritma PBKDF2 dan bcrypt menggunakan sejumlah perulangan atau pemutaran dari campuran. Ini sengaja memperlambat penyerang, membuat serangan terhadap sandi campuran lebih keras. Bagaimanapun, seiring kekuatan komputer meningkat, sejumlah perulangan butuh ditingkatkan. Kami telah memilih awalan yang masuk akal (dan akan meningkatkannya dengan setiap terbitan dari Django), tetapi anda mungkin berharap untuk menyetem keatas dan kebawah, tergantung pada kebutuhan keamanan anda dan kekuatan pengolahan yang tersedia. Untuk melakukannya, anda akan mensubkelaskan algoritma yang sesuai dan menimpa parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code>. Sebagai contoh, untuk meningkatkan sejumlah perulangan digunakan oleh awalan algoritma PBKDF2:</p>\n<ol class=\"arabic\">\n<li><p>Membuat sebuah 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<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyPBKDF2PasswordHasher</span><span class=\"p\">(</span><span class=\"n\">PBKDF2PasswordHasher</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">iterations</span> <span class=\"o\">=</span> <span class=\"n\">PBKDF2PasswordHasher</span><span class=\"o\">.</span><span class=\"n\">iterations</span> <span class=\"o\">*</span> <span class=\"mi\">100</span>\n</code></pre></div>\n<p>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/3.2/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PASSWORD_HASHERS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;myproject.hashers.MyPBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ol>\n<p>Itu dia -- sekarang pemasangan Django anda akan menggunakan perulangan lebih ketika itu menyimpan sandi menggunakan PBKDF2.</p>\n</section>\n<section id=\"argon2\">\n<h4>Argon2<a class=\"heading-anchor\" href=\"#argon2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Argon2 mempunyai tiga atribut 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>\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>However, Django can only upgrade passwords that use algorithms mentioned in\n<a class=\"reference internal\" href=\"/id/3.2/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a>, so as you upgrade to new systems you should make\nsure never to <em>remove</em> entries from this list. If you do, users using\nunmentioned algorithms won't be able to upgrade. Hashed passwords will be\nupdated when increasing (or decreasing) the number of PBKDF2 iterations, bcrypt\nrounds, or argon2 attributes.</p>\n<p>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 mempunyai basisdata yang ada dengan yang terlama, campuran lemah seperti MD5 atau SHA1, anda mungkin ingin meningkatkan campuran tersebut anda sendiri daripada menunggu peninggkatan terjadi ketika pengguna masuk (yang mungkin tidak pernah terjadi jika pengguna tidak kembali ke situs anda). Di kasus ini, anda dapat menggunakan pencampur sandi &quot;wrapped&quot;.</p>\n<p>Untuk contoh ini, kami akan memindahkan kumpulan dari campuran SHA1 untuk menggunakan PBKDF2(SHA1(password)) dan menambah pencampur sandi sesuai untuk memeriksa jika pengguna memasukkan sandi benar pada masuk. Kami menganggap kami sedang menggunakan model <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> siap-pakai dan bahwa proyek kami mempunyai sebuah aplikasi <code class=\"docutils literal notranslate\"><span class=\"pre\">accounts</span></code>. Anda dapat merubah pola untuk bekerja dengan algoritma apapun atau dengan penyesuaian model user.</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> <span class=\"n\">SHA1PasswordHasher</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PBKDF2WrappedSHA1PasswordHasher</span><span class=\"p\">(</span><span class=\"n\">PBKDF2PasswordHasher</span><span class=\"p\">):</span>\n    <span class=\"n\">algorithm</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;pbkdf2_wrapped_sha1&#39;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">encode_sha1_hash</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">sha1_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">encode</span><span class=\"p\">(</span><span class=\"n\">sha1_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">encode</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"n\">_</span><span class=\"p\">,</span> <span class=\"n\">_</span><span class=\"p\">,</span> <span class=\"n\">sha1_hash</span> <span class=\"o\">=</span> <span class=\"n\">SHA1PasswordHasher</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">encode</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s1\">&#39;$&#39;</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">encode_sha1_hash</span><span class=\"p\">(</span><span class=\"n\">sha1_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">iterations</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>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_sha1_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\">PBKDF2WrappedSHA1PasswordHasher</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">forwards_func</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"p\">,</span> <span class=\"n\">schema_editor</span><span class=\"p\">):</span>\n    <span class=\"n\">User</span> <span class=\"o\">=</span> <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s1\">&#39;auth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;User&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">users</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">password__startswith</span><span class=\"o\">=</span><span class=\"s1\">&#39;sha1$&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">hasher</span> <span class=\"o\">=</span> <span class=\"n\">PBKDF2WrappedSHA1PasswordHasher</span><span class=\"p\">()</span>\n    <span class=\"k\">for</span> <span class=\"n\">user</span> <span class=\"ow\">in</span> <span class=\"n\">users</span><span class=\"p\">:</span>\n        <span class=\"n\">algorithm</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">,</span> <span class=\"n\">sha1_hash</span> <span class=\"o\">=</span> <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">password</span><span class=\"o\">.</span><span class=\"n\">split</span><span class=\"p\">(</span><span class=\"s1\">&#39;$&#39;</span><span class=\"p\">,</span> <span class=\"mi\">2</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">password</span> <span class=\"o\">=</span> <span class=\"n\">hasher</span><span class=\"o\">.</span><span class=\"n\">encode_sha1_hash</span><span class=\"p\">(</span><span class=\"n\">sha1_hash</span><span class=\"p\">,</span> <span class=\"n\">salt</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">update_fields</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"s1\">&#39;password&#39;</span><span class=\"p\">])</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Migration</span><span class=\"p\">(</span><span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">Migration</span><span class=\"p\">):</span>\n\n    <span class=\"n\">dependencies</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;accounts&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;0001_initial&#39;</span><span class=\"p\">),</span>\n        <span class=\"c1\"># replace this with the latest migration in contrib.auth</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;auth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;####_migration_name&#39;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n\n    <span class=\"n\">operations</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n        <span class=\"n\">migrations</span><span class=\"o\">.</span><span class=\"n\">RunPython</span><span class=\"p\">(</span><span class=\"n\">forwards_func</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n</code></pre></figure>\n<p>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/3.2/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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;accounts.hashers.PBKDF2WrappedSHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>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=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.Argon2PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptSHA256PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.BCryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.SHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.MD5PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.UnsaltedMD5PasswordHasher&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth.hashers.CryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>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\">sha1</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">md5</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">unsalted_sha1</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">unsalted_md5</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">crypt</span></code></p></li>\n</ul>\n</section>\n<section id=\"writing-your-own-hasher\">\n<span id=\"write-your-own-password-hasher\"></span><h3>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>The <a class=\"reference internal\" href=\"#module-django.contrib.auth.hashers\" title=\"django.contrib.auth.hashers\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.hashers</span></code></a> module provides a set of functions\nto create and validate hashed passwords. You can use them independently\nfrom the <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> model.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.check_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">check_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">encoded</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.check_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Jika anda suka secara manual autentifikasi pengguna dengan membandingkan sandi teks-polos pada sandi dicampur di basisdata, gunakan fungsi nyaman <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>. Itu mengambil dua argumen: sandi teks-polos untuk memeriksa, dan nilai penuh dari bidang <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> pengguna di basisdata untuk memeriksa terhadap, dan mengembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> jika mereka cocok, <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> sebaliknya.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.make_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">make_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">salt</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">hasher</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'default'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.make_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Creates a hashed password in the format used by this application. It takes\none mandatory argument: the password in plain-text (string or bytes).\nOptionally, you can provide a salt and a hashing algorithm to use, if you\ndon't want to use the defaults (first entry of <code class=\"docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code>\nsetting). See <a class=\"reference internal\" href=\"#auth-included-hashers\"><span class=\"std std-ref\">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<aside class=\"version-note version-changed\" data-version=\"3.1\">\n<p class=\"version-note-title\">Changed in Django 3.1</p><p>Parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> harus berupa string atau byte jika tidak <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>.</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.is_password_usable\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_password_usable</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">encoded_password</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.is_password_usable\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Mengembalikan <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> jika sandi adalah hasil dari <a class=\"reference internal\" href=\"/id/3.2/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password\" title=\"django.contrib.auth.models.User.set_unusable_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">User.set_unusable_password()</span></code></a>.</p>\n</dd></dl>\n\n</section>\n<section id=\"module-django.contrib.auth.password_validation\">\n<span id=\"id2\"></span><span id=\"password-validation\"></span><h2>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>Users often choose poor passwords. To help mitigate this problem, Django\noffers pluggable password validation. You can configure multiple password\nvalidators at the same time. A few validators are included in Django, but you\ncan write your own as well.</p>\n<p>Setiap pengesah sandi harus menyediakan teks bantuan untuk menjelaskan persyaratan ke pengguna, mensahkan sandi diberikan dan mengembalikan sebuah pesan kesalahan jika itu tidak memenuhi persyaratan, dan pilihannya menerima sandi yang telah disetel. Pengesah dapat juga mempunyai pengaturan pilihan untuk mendenda menyesuaikan perilaku mereka.</p>\n<p>Validation is controlled by the <a class=\"reference internal\" href=\"/id/3.2/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a> setting.\nThe default for the setting is an empty list, which means no validators are\napplied. In new projects created with the default <a class=\"reference internal\" href=\"/id/3.2/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a>\ntemplate, a set of validators is enabled by default.</p>\n<p>Secara awalan, pengesah digunakan dalam formulir untuk menyetel kembali atau merubah sandi dan di perintah pengelolaan <a class=\"reference internal\" href=\"/id/3.2/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/3.2/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/3.2/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">AUTH_PASSWORD_VALIDATORS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.UserAttributeSimilarityValidator&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.MinimumLengthValidator&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;OPTIONS&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;min_length&#39;</span><span class=\"p\">:</span> <span class=\"mi\">9</span><span class=\"p\">,</span>\n        <span class=\"p\">}</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.CommonPasswordValidator&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;NAME&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.contrib.auth.password_validation.NumericPasswordValidator&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>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>, which checks whether the password meets a minimum\nlength. This validator is configured with a custom option: it now requires\nthe minimum length to be nine characters, instead of the default eight.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>, which checks whether the password occurs in a\nlist of common passwords. By default, it compares to an included list of\n20,000 common passwords.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code>, yang memeriksa apakah sandi tidak sepenuhnya numerik.</p></li>\n</ul>\n<p>For <code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">CommonPasswordValidator</span></code>,\nwe're using the default settings in this example. <code class=\"docutils literal notranslate\"><span class=\"pre\">NumericPasswordValidator</span></code>\nhas no settings.</p>\n<p>Teks bantuan dan kesalahan apapun dari pengesah sandi selalu dikembalikan agar mereka didaftarkan di <a class=\"reference internal\" href=\"/id/3.2/ref/settings/#std-setting-AUTH_PASSWORD_VALIDATORS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_PASSWORD_VALIDATORS</span></code></a>.</p>\n</section>\n<section id=\"included-validators\">\n<h3>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>Mengesahkan apakah sandi memenuhi panjang minimal. Panjang minimal dapat disesuaikan dengan parameter <code class=\"docutils literal notranslate\"><span class=\"pre\">min_length</span></code>.</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">UserAttributeSimilarityValidator</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user_attributes</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DEFAULT_USER_ATTRIBUTES</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">max_similarity</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">0.7</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.UserAttributeSimilarityValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Mengesahkan apakah sandi cukup berbeda dari atribut tertentu dari 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>The maximum allowed similarity of passwords can be set on a scale of 0.1\nto 1.0 with the <code class=\"docutils literal notranslate\"><span class=\"pre\">max_similarity</span></code> parameter. This is compared to the\nresult of <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>. A value of 0.1\nrejects passwords unless they are substantially different from the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code>, whereas a value of 1.0 rejects only passwords that are\nidentical to an attribute's value.</p>\n<aside class=\"version-note version-changed\" data-version=\"2.2.26\">\n<p class=\"version-note-title\">Changed in Django 2.2.26</p><p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">max_similarity</span></code> parameter was limited to a minimum value of 0.1.</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.CommonPasswordValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">CommonPasswordValidator</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_list_path</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DEFAULT_PASSWORD_LIST_PATH</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.CommonPasswordValidator\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Validates whether the password is not a common password. This converts the\npassword to lowercase (to do a case-insensitive comparison) and checks it\nagainst a list of 20,000 common password created by <a class=\"reference external\" href=\"https://gist.github.com/roycewilliams/281ce539915a947a23db17137d91aeb7\">Royce Williams</a>.</p>\n<p><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</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>Mengesahkan apakah sandi tidak sepenuhnya numerik.</p>\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/3.2/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/3.2/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/3.2/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/3.2/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/3.2/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>If Django's built-in validators are not sufficient, you can write your own\npassword validators. Validators have a fairly small interface. They must\nimplement two methods:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">validate(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">user=None)</span></code>: validate a password. Return\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> if the password is valid, or raise a\n<a class=\"reference internal\" href=\"/id/3.2/ref/exceptions/#django.core.exceptions.ValidationError\" title=\"django.core.exceptions.ValidationError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValidationError</span></code></a> with an error message if the\npassword is not valid. You must be able to deal with <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> being\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> - if that means your validator can't run, return <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> for no\nerror.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_help_text()</span></code>: 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/3.2/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<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MinimumLengthValidator</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">min_length</span><span class=\"o\">=</span><span class=\"mi\">8</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span> <span class=\"o\">=</span> <span class=\"n\">min_length</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">validate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">ValidationError</span><span class=\"p\">(</span>\n                <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;This password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span><span class=\"p\">),</span>\n                <span class=\"n\">code</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_too_short&#39;</span><span class=\"p\">,</span>\n                <span class=\"n\">params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;min_length&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">},</span>\n            <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_help_text</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">_</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;Your password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span>\n            <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s1\">&#39;min_length&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">}</span>\n        <span class=\"p\">)</span>\n</code></pre></div>\n<p>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":"Increasing the salt entropy","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":"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/3.2/topics/"},{"docname":"topics/auth/index","title":"Otentifikasi pengguna di Django","url":"/id/3.2/topics/auth/"}],"prev":{"docname":"topics/auth/default","title":"Menggunakan sistem pembuktian keaslian Django","url":"/id/3.2/topics/auth/default/"},"next":{"docname":"topics/auth/customizing","title":"Mengkostumisasi autentikasi di Django","url":"/id/3.2/topics/auth/customizing/"},"formats":{"html":"/id/3.2/topics/auth/passwords/","markdown":"/id/3.2/topics/auth/passwords.md","json":"/id/3.2/topics/auth/passwords.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/topics/auth/passwords.txt","official":"https://docs.djangoproject.com/id/3.2/topics/auth/passwords/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}