{"title":"Gerenciamento de senhas no Django","version":"4.0","locale":"pt-br","docname":"topics/auth/passwords","url":"/pt-br/4.0/topics/auth/passwords/","canonical":"https://djangodocs.dev/pt-br/4.0/topics/auth/passwords/","summary":"O gerenciamento de senha é algo que não deve ser reinventado desnecessariamente, e o Django se esforça para fornecer um conjunto de ferramentas seguras e flexíveis…","html":"<h1>Gerenciamento de senhas no Django<a class=\"heading-anchor\" href=\"#password-management-in-django\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>O gerenciamento de senha é algo que não deve ser reinventado desnecessariamente, e o Django se esforça para fornecer um conjunto de ferramentas seguras e flexíveis para gerenciar senhas de usuários. Este documento descreve como o Django armazena senhas, como o armazenamento de “hashes” pode ser configurado, e algumas utilidade para trabalhar com senhas criptografadas.</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">Ver também</p>\n<p>Mesmo que os usuários usem senha fortes, ataques podem ser capazes de bisbilhotar suas conexões. Use conexões <a class=\"reference internal\" href=\"/pt-br/4.0/topics/security/#security-recommendation-ssl\"><span class=\"std std-ref\">HTTPS</span></a> para evitar o envio de senhas (ou qualquer outro dado sensível) sobre conexões HTTP porque eles estarão vulneráveis a sequestros de senhas.</p>\n</aside>\n<section id=\"how-django-stores-passwords\">\n<span id=\"auth-password-storage\"></span><h2>Como o Django armazena as senhas<a class=\"heading-anchor\" href=\"#how-django-stores-passwords\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>O Django fornece um sistema flexível de armazenamento de senhas e usa PBKDF2 por padrão.</p>\n<p>O atributo <a class=\"reference internal\" href=\"/pt-br/4.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> de um objeto <a class=\"reference internal\" href=\"/pt-br/4.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> é uma string nesse formato:</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>Estes são os componentes usados para armazenamento de senha do “User”, separados pelo caracter de sinal do dólar e consistem em: o algoritmo de “hash”, o número de iterações do algoritmo (fator de trabalho), o “salt” randômico, e o “hash” de senha resultante. O algoritmo é um dos vários algoritmos “hash” de via única ou de armazenamento de senha que o Django pode usar; veja abaixo. O iterações descreve o número de vezes que o algoritmo é executado sobre o “hash”. “Salt” é a string randômica inicial usada e o “hash” é o resultado da função de via única.</p>\n<p>Por padrão, Django usa o algoritmo <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/PBKDF2\">PBKDF2</a> com um hash SHA256, um mecanismo de elasticidade de senha recomendado pelo <a class=\"reference external\" href=\"https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf\">NIST</a>. Isso deve ser suficiente para a maior parte dos usuários: é bastante seguro, e requer quantidades massivas de tempo computacional para quebrar.</p>\n<p>Contudo, dependendo das suas necessidades, você pode escolher um algoritmo diferente, ou até mesmo usar um algoritmo customizado para suprir suas necessidades específicas de segurança. Novamente, a maioria dos usuários não precisam disso – se você não tem certeza, provavelmente não precisa. Se você precisa, por favor, leia:</p>\n<p>Django escolhe o algoritmo para usar consultando a configuração :setting:’PASSWORD_HASHERS’. Essa é uma lista de classes de algoritmos hash que essa instalação Django suporta. A primeira entrada nessa lista (ou seja, <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.PASSWORD_HASHERS[0]</span></code>) será usada para armazenar senhas, e todas as outras entradas são hashers válidos que podem ser usados para checar senhas existentes. Isso significa que, se você quiser usar um algoritmo diferente, precisará modificar <a class=\"reference internal\" href=\"/pt-br/4.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> para listar seu algoritmo preferido como primeira entrada na lista.</p>\n<p>O padrão para <a class=\"reference internal\" href=\"/pt-br/4.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=\"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.ScryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Isso significa que o Django vai usar o PBKFD2 para armazenar todas as senhas, mas vai suportar a conferência de senhas armazenadas com PBKDF2SHA1, <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">argon2</a>, and <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Bcrypt\">bcrypt</a>.</p>\n<p>As próximas seções descreverão jeitos comuns que usuários avançados podem querer usar para modificar essas configurações.</p>\n<section id=\"using-argon2-with-django\">\n<span id=\"argon2-usage\"></span><h3>Usando Argon2 com Django<a class=\"heading-anchor\" href=\"#using-argon2-with-django\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> é o campeão 2015 da ‘Competição de Senhas Hashing’_ uma competição aberta organizada organizada pela comunidade para eleger a próxima geração de algoritmo hashing. É um algoritmo projetado para não ser mais fácil de computar num hardware customizado do que é em um CPU normal.</p>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Argon2\">Argon2</a> não é o padrão do Django porque precisa de uma biblioteca de terceiros. A equipe da Competição de Senhas Hashing, contudo, recomenda o uso imediato de Argon2 em vez de outros algoritmos suportados pelo Django.</p>\n<p>Para usar Argon2 como seu algoritmo de armazenamento padrão, faça o seguinte:</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>Modificar <code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS`para</span> <span class=\"pre\">listar</span> <span class=\"pre\">primeiro</span> <span class=\"pre\">``Argon2PasswordHasher</span></code>. Ou seja, no seu arquivo de configurações, você colocaria:</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=\"s1\">&#39;django.contrib.auth.hashers.ScryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Mantenha ou adicione quaisquer entradas nessa lista se você precisa que o Django <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">atualize senhas</span></a>.</p>\n</li>\n</ol>\n</section>\n<section id=\"using-bcrypt-with-django\">\n<span id=\"bcrypt-usage\"></span><h3>Usando <code class=\"docutils literal notranslate\"><span class=\"pre\">bcrypt</span></code> com Django<a class=\"heading-anchor\" href=\"#using-bcrypt-with-django\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Bcrypt\">Bcrypt</a> é um algoritmo popular de armazenamento de senhas que é especificamente desenhado para armazenamento de senhas de longo prazo. Não é o padrão utilizado pelo Django porque requer uso de bibliotecas de terceiros, mas, já que muita gente pode querer usá-lo, Django suporta o o Bcrypt com mínimo esforço.</p>\n<p>Para utilizar Bcrypt como seu algoritmo de armazenamento padrão, faça o seguinte:</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>Modifique <a class=\"reference internal\" href=\"/pt-br/4.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> para listar primeiro <code class=\"docutils literal notranslate\"><span class=\"pre\">BCryptSHA256PasswordHasher</span></code>. Ou seja, no seu arquivo de configurações, você colocará:</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=\"s1\">&#39;django.contrib.auth.hashers.ScryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>Mantenha ou adicione quaisquer entradas nessa lista se você precisa que o Django <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">atualize senhas</span></a>.</p>\n</li>\n</ol>\n<p>É isso - agora a sua instalação do Django usará Bcrypt como o algoritmo de armazenamento padrão.</p>\n</section>\n<section id=\"using-scrypt-with-django\">\n<span id=\"scrypt-usage\"></span><h3>Using <code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> with Django<a class=\"heading-anchor\" href=\"#using-scrypt-with-django\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"version-note version-added\" data-version=\"4.0\">\n<p class=\"version-note-title\">New in Django 4.0</p></aside>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> is similar to PBKDF2 and bcrypt in utilizing a set number of iterations\nto slow down brute-force attacks. However, because PBKDF2 and bcrypt do not\nrequire a lot of memory, attackers with sufficient resources can launch\nlarge-scale parallel attacks in order to speed up the attacking process.\n<a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> is specifically designed to use more memory compared to other\npassword-based key derivation functions in order to limit the amount of\nparallelism an attacker can use, see <span class=\"target\" id=\"index-0\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc7914.html\"><strong>RFC 7914</strong></a> for more details.</p>\n<p>To use <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> as your default storage algorithm, do the following:</p>\n<ol class=\"arabic\">\n<li><p>Modify <a class=\"reference internal\" href=\"/pt-br/4.0/ref/settings/#std-setting-PASSWORD_HASHERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD_HASHERS</span></code></a> to list <code class=\"docutils literal notranslate\"><span class=\"pre\">ScryptPasswordHasher</span></code> first.\nThat is, in your settings file:</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.ScryptPasswordHasher&#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<p>Mantenha ou adicione quaisquer entradas nessa lista se você precisa que o Django <a class=\"reference internal\" href=\"#password-upgrades\"><span class=\"std std-ref\">atualize senhas</span></a>.</p>\n</li>\n</ol>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">scrypt</span></code> requires OpenSSL 1.1+.</p>\n</aside>\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 para este cabeçalho</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\">Implementation detail</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>Aumentando o fator de trabalho<a class=\"heading-anchor\" href=\"#increasing-the-work-factor\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<section id=\"pbkdf2-and-bcrypt\">\n<h4>PBKDF2 e bcrypt<a class=\"heading-anchor\" href=\"#pbkdf2-and-bcrypt\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>The PBKDF2 and bcrypt algorithms use a number of iterations or rounds of\nhashing. This deliberately slows down attackers, making attacks against hashed\npasswords harder. However, as computing power increases, the number of\niterations needs to be increased. We’ve chosen a reasonable default (and will\nincrease it with each release of Django), but you may wish to tune it up or\ndown, depending on your security needs and available processing power. To do so,\nyou’ll subclass the appropriate algorithm and override the <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code>\nparameter (use the <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> parameter when subclassing a bcrypt hasher). For\nexample, to increase the number of iterations used by the default PBKDF2\nalgorithm:</p>\n<ol class=\"arabic\">\n<li><p>Criar uma subclasse de <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>Salve isso em algum lugar no seu projeto. Por exemplo, você pode coloca-lo em um arquivo como <code class=\"docutils literal notranslate\"><span class=\"pre\">meuprojeto/hashers.py</span></code>.</p>\n</li>\n<li><p>Adicione seu novo hasher como a primeira entrada em: setting:PASSWORD_HASHERS:</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=\"s1\">&#39;django.contrib.auth.hashers.ScryptPasswordHasher&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n</ol>\n<p>É isso – agora seu Django install usará mais iterações ao armazenar senhas usando PBKDF2.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p>bcrypt <code class=\"docutils literal notranslate\"><span class=\"pre\">rounds</span></code> is a logarithmic work factor, e.g. 12 rounds means\n<code class=\"docutils literal notranslate\"><span class=\"pre\">2</span> <span class=\"pre\">**</span> <span class=\"pre\">12</span></code> iterations.</p>\n</aside>\n</section>\n<section id=\"argon2\">\n<h4>Argon2<a class=\"heading-anchor\" href=\"#argon2\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Argon2 tem três atributos que podem ser personalizados:</p>\n<ol class=\"arabic simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> controla o número de iterações dentro do hash.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> controla o tamanho da memória que deve ser usada durante a computação do hash.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> controla quantas CPUs podem ser paralelizadas na computação do hash.</p></li>\n</ol>\n<p>Os valores padrão desses atributos provavelmente estarão bons para você. Se você determinar que o seu hash de senha está muito rápido ou muito lento, você pode ajusta-lo como segue:</p>\n<ol class=\"arabic simple\">\n<li><p>Escolha <code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> para ser o número de threads que você pode disponibilizar para computar o hash.</p></li>\n<li><p>Escolha <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> para ser o quanto de memória em KiB que você pode disponibilizar.</p></li>\n<li><p>Ajuste <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> e meça o tempo gasto para gerar o hash de uma senha. Escolha um <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> que tome um tempo aceitável para você. Se <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code> configurado para 1 for inaceitavelmente lento para você, reduza <code class=\"docutils literal notranslate\"><span class=\"pre\">time_cost</span></code>.</p></li>\n</ol>\n<aside class=\"admonition-memory-cost-interpretation admonition\">\n<p class=\"admonition-title\"><code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> interpretação</p>\n<p>O utilitário de linha de comando argon2 e algumas outras bibliotecas interpretam o parâmetro <code class=\"docutils literal notranslate\"><span class=\"pre\">memory_cost</span></code> diferentemente do valor que Django usa. A conversão é dada por <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 para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h4>\n<aside class=\"version-note version-added\" data-version=\"4.0\">\n<p class=\"version-note-title\">New in Django 4.0</p></aside>\n<p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> has four attributes that can be customized:</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.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code></p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">parallelism</span></code> controls how many threads will run in parallel.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> limits the maximum size of memory that can be used during the\ncomputation of the hash. Defaults to <code class=\"docutils literal notranslate\"><span class=\"pre\">0</span></code>, which means the default\nlimitation from the OpenSSL library.</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.</p>\n<aside class=\"admonition-estimating-memory-usage admonition\">\n<p class=\"admonition-title\">Estimating memory usage</p>\n<p>The minimum memory requirement of <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Scrypt\">scrypt</a> is:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"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>so you may need to tweak <code class=\"docutils literal notranslate\"><span class=\"pre\">maxmem</span></code> when changing the <code class=\"docutils literal notranslate\"><span class=\"pre\">work_factor</span></code> or\n<code class=\"docutils literal notranslate\"><span class=\"pre\">block_size</span></code> values.</p>\n</aside>\n</section>\n</section>\n<section id=\"password-upgrading\">\n<span id=\"password-upgrades\"></span><h3>Atualização de senha<a class=\"heading-anchor\" href=\"#password-upgrading\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Quando usuários entram, se suas senhas estão armazenadas com qualquer outra coisa que não o o algoritmo preferido, Django atualizará automaticamente o algoritmo para o preferido. Isto significa que instalações antigas de Django ficarão mais seguras a medida que os usuários entram, isso também significa que você pode mudar para novos (e melhores) algoritmos de armazenamento quando eles forem inventados.</p>\n<p>However, Django can only upgrade passwords that use algorithms mentioned in\n<a class=\"reference internal\" href=\"/pt-br/4.0/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>Esteja ciente que se nem todas as senhas armazenadas em seu banco de dados estiverem codificadas através do algoritmo padrão de hash, você pode estar vulnerável a ataques de enumeração de usuários baseado em tempo devido a uma diferença entre a duração do pedido de login para um usuário com uma senha codificada por um algoritmo não-padrão e a duração de um pedido de login para um usuário inexistente (o qual roda o hash padrão). Você pode ser capaz de mitigar isso:ref:atualizando hashes de senhas mais antigos &lt;wrapping-password-hashers&gt;.</p>\n</section>\n<section id=\"password-upgrading-without-requiring-a-login\">\n<span id=\"wrapping-password-hashers\"></span><h3>Atualização de senha sem exigência de login<a class=\"heading-anchor\" href=\"#password-upgrading-without-requiring-a-login\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Se você tem um banco de dados existente com um hash mais antigo e fraco, tal como MD5 ou SHA1, você pode desejar atualizar esses hashes você mesmo em vez de esperar que a atualização aconteça quando um usuário faça login (o que pode nunca acontecer se um usuário não voltar ao seu site). Neste caso você pode utilizar um hasher de senha “envolta”.</p>\n<p>Para esse exemplo, vamos migrar a coleção de hashes SHA1 para usar PBKDF2(SHA1(password)) e adicionar o hasher de senha correspondente para checar se um usuário inserir a senha correta no login. Vamos assumir que estamos usando o modelo <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> padrão e o nosso projeto tem uma aplicação <code class=\"docutils literal notranslate\"><span class=\"pre\">contas</span></code>. Você pode modificar o padrão para trabalhar com qualquer algoritmo ou com um modelo de usuário customizado.</p>\n<p>Primeiro, vamos adicionar um hasher customizado:</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>A migração pode parecer algo como:</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>Tenha cuidado que essa migração deve ser tomará uma ordem de vários minutos para milhares de usuários, dependendo da velocidade do seu hardware.</p>\n<p>Finalmente, vamos adicionar a configuração <a class=\"reference internal\" href=\"/pt-br/4.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=\"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>Inclua quaisquer outros hashers que seu site usa nessa lista.</p>\n</section>\n<section id=\"included-hashers\">\n<span id=\"auth-included-hashers\"></span><h3>Hashers incluídos<a class=\"heading-anchor\" href=\"#included-hashers\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A lista completa de hashers incluídas no Django são:</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.ScryptPasswordHasher&#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>Os nomes de algoritmos correspondentes são:</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\">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>Escrevendo seu próprio hasher<a class=\"heading-anchor\" href=\"#writing-your-own-hasher\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you write your own password hasher that contains a work factor such as a\nnumber of iterations, you should implement a\n<code class=\"docutils literal notranslate\"><span class=\"pre\">harden_runtime(self,</span> <span class=\"pre\">password,</span> <span class=\"pre\">encoded)</span></code> method to bridge the runtime gap\nbetween the work factor supplied in the <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> password and the default\nwork factor of the hasher. This prevents a user enumeration timing attack due\nto  difference between a login request for a user with a password encoded in an\nolder number of iterations and a nonexistent user (which runs the default\nhasher’s default number of iterations).</p>\n<p>Taking PBKDF2 as example, if <code class=\"docutils literal notranslate\"><span class=\"pre\">encoded</span></code> contains 20,000 iterations and the\nhasher’s default <code class=\"docutils literal notranslate\"><span class=\"pre\">iterations</span></code> is 30,000, the method should run <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code>\nthrough another 10,000 iterations of PBKDF2.</p>\n<p>If your hasher doesn’t have a work factor, implement the method as a no-op\n(<code class=\"docutils literal notranslate\"><span class=\"pre\">pass</span></code>).</p>\n</section>\n</section>\n<section id=\"module-django.contrib.auth.hashers\">\n<span id=\"manually-managing-a-user-s-password\"></span><h2>Manually managing a user’s password<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.hashers\"><span class=\"visually-hidden\">Link para este cabeçalho</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 para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>If you’d like to manually authenticate a user by comparing a plain-text\npassword to the hashed password in the database, use the convenience\nfunction <a class=\"reference internal\" href=\"#django.contrib.auth.hashers.check_password\" title=\"django.contrib.auth.hashers.check_password\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">check_password()</span></code></a>. It takes two arguments: the plain-text\npassword to check, and the full value of a user’s <code class=\"docutils literal notranslate\"><span class=\"pre\">password</span></code> field in the\ndatabase to check against, and returns <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if they match, <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>\notherwise.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.hashers.make_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">make_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">salt</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">hasher</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'default'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.hashers.make_password\"><span class=\"visually-hidden\">Link para esta definição</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\">Hashers incluídos</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 para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Returns <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> if the password is a result of\n<a class=\"reference internal\" href=\"/pt-br/4.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>Validação de senha<a class=\"heading-anchor\" href=\"#module-django.contrib.auth.password_validation\"><span class=\"visually-hidden\">Link para este cabeçalho</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>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 receive passwords that have been set.\nValidators can also have optional settings to fine tune their behavior.</p>\n<p>Validation is controlled by the <a class=\"reference internal\" href=\"/pt-br/4.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> 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=\"/pt-br/4.0/ref/django-admin/#django-admin-startproject\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">startproject</span></code></a>\ntemplate, a set of validators is enabled by default.</p>\n<p>By default, validators are used in the forms to reset or change passwords and\nin the <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-createsuperuser\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">createsuperuser</span></code></a> and <a class=\"reference internal\" href=\"/pt-br/4.0/ref/django-admin/#django-admin-changepassword\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">changepassword</span></code></a> management\ncommands. Validators aren’t applied at the model level, for example in\n<code class=\"docutils literal notranslate\"><span class=\"pre\">User.objects.create_user()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">create_superuser()</span></code>, because we assume\nthat developers, not users, interact with Django at that level and also because\nmodel validation doesn’t automatically run as part of creating models.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Nota</p>\n<p>Validação de senha pode previnir que o usuário utilize muitos tipos de senhas fracas. No entanto, o fato de uma senha passar em todos os validadores não garante que a senha é forte. Existem muitos outros fatores que podem enfraquecer uma senha que não é detectado nem mesmo pelos validadores de senha mais avançados.</p>\n</aside>\n<section id=\"enabling-password-validation\">\n<h3>Habilitando validação de senha<a class=\"heading-anchor\" href=\"#enabling-password-validation\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A validação de senha é configurada utilizando a variável <a class=\"reference internal\" href=\"/pt-br/4.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=\"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>Este exemplo habilita todos os quatro validadores incluídos:</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">UserAttributeSimilarityValidator</span></code>, que verifica a similaridade entre a senha e um conjunto de atributos do usuário.</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>, que verifica se a senha não é completamente numérica.</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>Os textos de ajuda e qualquer erro dos validadores de senha sempre retornam na ordem que eles foram listados no <a class=\"reference internal\" href=\"/pt-br/4.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<h3>Validadores incluídos<a class=\"heading-anchor\" href=\"#included-validators\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django inclui quatro validadores:</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 para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Valida se a senha possui um tamanho mínimo. O tamanho mínimo pode ser customizado com o parâmetro <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 para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Valida se a senha é suficientemente diferente dos atributos do usuário.</p>\n<p>O parâmetro <code class=\"docutils literal notranslate\"><span class=\"pre\">user_attributes</span></code> deve ser um iterável de nomes de atributos de usuário para serem comparados. Se este argumento não for fornecido, o padrão será utilizado: <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>. Atributos que não existem são ignorados.</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=\"(em 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 para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Validates whether the password is not a common password. This converts the\npassword to lowercase (to do a case-insensitive comparison) and checks it\nagainst a list of 20,000 common password created by <a class=\"reference external\" href=\"https://gist.github.com/roycewilliams/281ce539915a947a23db17137d91aeb7\">Royce Williams</a>.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">password_list_path</span></code> can be set to the path of a custom file of\ncommon passwords. This file should contain one lowercase password per line\nand may be plain text or gzipped.</p>\n</dd></dl>\n\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.NumericPasswordValidator\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">NumericPasswordValidator</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.NumericPasswordValidator\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Validates whether the password is not entirely numeric.</p>\n</dd></dl>\n\n</section>\n<section id=\"integrating-validation\">\n<h3>Integrating validation<a class=\"heading-anchor\" href=\"#integrating-validation\"><span class=\"visually-hidden\">Link para este cabeçalho</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>There are a few functions in <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.password_validation</span></code> that\nyou can call from your own forms or other code to integrate password\nvalidation. This can be useful if you use custom forms for password setting,\nor if you have API calls that allow passwords to be set, for example.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.validate_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">validate_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.validate_password\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Validates a password. If all validators find the password valid, returns\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>. If one or more validators reject the password, raises a\n<a class=\"reference internal\" href=\"/pt-br/4.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> with all the error messages\nfrom the validators.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> object is optional: if it’s not provided, some validators may\nnot be able to perform any validation and will accept any password.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_changed\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_changed</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_changed\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Informs all validators that the password has been changed. This can be used\nby validators such as one that prevents password reuse. This should be\ncalled once the password has been successfully changed.</p>\n<p>For subclasses of <a class=\"reference internal\" href=\"/pt-br/4.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>,\nthe password field will be marked as “dirty” when calling\n<a class=\"reference internal\" href=\"/pt-br/4.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> which\ntriggers a call to <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed()</span></code> after the user is saved.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_validators_help_texts\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_validators_help_texts</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_validators_help_texts\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Returns a list of the help texts of all validators. These explain the\npassword requirements to the user.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.password_validators_help_text_html\">\n<span class=\"sig-name descname\"><span class=\"pre\">password_validators_help_text_html</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password_validators</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.password_validators_help_text_html\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Returns an HTML string with all help texts in an <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;ul&gt;</span></code>. This is\nhelpful when adding password validation to forms, as you can pass the\noutput directly to the <code class=\"docutils literal notranslate\"><span class=\"pre\">help_text</span></code> parameter of a form field.</p>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.password_validation.get_password_validators\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_password_validators</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">validator_config</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.password_validation.get_password_validators\"><span class=\"visually-hidden\">Link para esta definição</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Returns a set of validator objects based on the <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code>\nparameter. By default, all functions use the validators defined in\n<a class=\"reference internal\" href=\"/pt-br/4.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>, but by calling this function with an\nalternate set of validators and then passing the result into the\n<code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> parameter of the other functions, your custom set\nof validators will be used instead. This is useful when you have a typical\nset of validators to use for most scenarios, but also have a special\nsituation that requires a custom set. If you always use the same set\nof validators, there is no need to use this function, as the configuration\nfrom <a class=\"reference internal\" href=\"/pt-br/4.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> is used by default.</p>\n<p>The structure of <code class=\"docutils literal notranslate\"><span class=\"pre\">validator_config</span></code> is identical to the\nstructure of <a class=\"reference internal\" href=\"/pt-br/4.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>. The return value of\nthis function can be passed into the <code class=\"docutils literal notranslate\"><span class=\"pre\">password_validators</span></code> parameter\nof the functions listed above.</p>\n</dd></dl>\n\n<p>Note that where the password is passed to one of these functions, this should\nalways be the clear text password - not a hashed password.</p>\n</section>\n<section id=\"writing-your-own-validator\">\n<h3>Escrevendo seu próprio validador<a class=\"heading-anchor\" href=\"#writing-your-own-validator\"><span class=\"visually-hidden\">Link para este cabeçalho</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=\"/pt-br/4.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> with an error message if the\npassword is not valid. You must be able to deal with <code class=\"docutils literal notranslate\"><span class=\"pre\">user</span></code> being\n<code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> - if that means your validator can’t run, return <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> for no\nerror.</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">get_help_text()</span></code>: provide a help text to explain the requirements to\nthe user.</p></li>\n</ul>\n<p>Any items in the <code class=\"docutils literal notranslate\"><span class=\"pre\">OPTIONS</span></code> in <a class=\"reference internal\" href=\"/pt-br/4.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> for your\nvalidator will be passed to the constructor. All constructor arguments should\nhave a default value.</p>\n<p>Here’s a basic example of a validator, with one optional setting:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.exceptions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ValidationError</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils.translation</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">gettext</span> <span class=\"k\">as</span> <span class=\"n\">_</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MinimumLengthValidator</span><span class=\"p\">:</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__init__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">min_length</span><span class=\"o\">=</span><span class=\"mi\">8</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span> <span class=\"o\">=</span> <span class=\"n\">min_length</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">validate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">user</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">if</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">)</span> <span class=\"o\">&lt;</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">ValidationError</span><span class=\"p\">(</span>\n                <span class=\"n\">_</span><span class=\"p\">(</span><span class=\"s2\">&quot;This password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span><span class=\"p\">),</span>\n                <span class=\"n\">code</span><span class=\"o\">=</span><span class=\"s1\">&#39;password_too_short&#39;</span><span class=\"p\">,</span>\n                <span class=\"n\">params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">&#39;min_length&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">},</span>\n            <span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_help_text</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">_</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;Your password must contain at least </span><span class=\"si\">%(min_length)d</span><span class=\"s2\"> characters.&quot;</span>\n            <span class=\"o\">%</span> <span class=\"p\">{</span><span class=\"s1\">&#39;min_length&#39;</span><span class=\"p\">:</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">min_length</span><span class=\"p\">}</span>\n        <span class=\"p\">)</span>\n</code></pre></div>\n<p>You can also implement <code class=\"docutils literal notranslate\"><span class=\"pre\">password_changed(password,</span> <span class=\"pre\">user=None</span></code>), which will\nbe called after a successful password change. That can be used to prevent\npassword reuse, for example. However, if you decide to store a user’s previous\npasswords, you should never do so in clear text.</p>\n</section>\n</section>","rootId":"password-management-in-django","toc":[{"title":"Como o Django armazena as senhas","anchor":"how-django-stores-passwords","children":[{"title":"Usando Argon2 com Django","anchor":"using-argon2-with-django","children":[]},{"title":"Usando bcrypt com Django","anchor":"using-bcrypt-with-django","children":[]},{"title":"Using scrypt with Django","anchor":"using-scrypt-with-django","children":[]},{"title":"Increasing the salt entropy","anchor":"increasing-the-salt-entropy","children":[]},{"title":"Aumentando o fator de trabalho","anchor":"increasing-the-work-factor","children":[{"title":"PBKDF2 e bcrypt","anchor":"pbkdf2-and-bcrypt","children":[]},{"title":"Argon2","anchor":"argon2","children":[]},{"title":"scrypt","anchor":"scrypt","children":[]}]},{"title":"Atualização de senha","anchor":"password-upgrading","children":[]},{"title":"Atualização de senha sem exigência de login","anchor":"password-upgrading-without-requiring-a-login","children":[]},{"title":"Hashers incluídos","anchor":"included-hashers","children":[]},{"title":"Escrevendo seu próprio hasher","anchor":"writing-your-own-hasher","children":[]}]},{"title":"Manually managing a user’s password","anchor":"module-django.contrib.auth.hashers","children":[]},{"title":"Validação de senha","anchor":"module-django.contrib.auth.password_validation","children":[{"title":"Habilitando validação de senha","anchor":"enabling-password-validation","children":[]},{"title":"Validadores incluídos","anchor":"included-validators","children":[]},{"title":"Integrating validation","anchor":"integrating-validation","children":[]},{"title":"Escrevendo seu próprio validador","anchor":"writing-your-own-validator","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Usando o Django","url":"/pt-br/4.0/topics/"},{"docname":"topics/auth/index","title":"Autenticação de usuário no Django","url":"/pt-br/4.0/topics/auth/"}],"prev":{"docname":"topics/auth/default","title":"Usando o sistema de autenticação Django","url":"/pt-br/4.0/topics/auth/default/"},"next":{"docname":"topics/auth/customizing","title":"Personalizando a autenticação no Django","url":"/pt-br/4.0/topics/auth/customizing/"},"formats":{"html":"/pt-br/4.0/topics/auth/passwords/","markdown":"/pt-br/4.0/topics/auth/passwords.md","json":"/pt-br/4.0/topics/auth/passwords.json"},"source":"https://github.com/django/django/blob/stable/4.0.x/docs/topics/auth/passwords.txt","official":"https://docs.djangoproject.com/pt-br/4.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","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}