Reescrevendo o Gerador de Senhas

Política de senha


Senhas fora da política


Tive a sensação de que já escrevi uma função para gerar senhas cinco vezes. E ele fazia diferente sempre. E a razão para isso são os diferentes requisitos de senha para diferentes projetos e ferramentas. Não haverá código complexo, apenas um resumo de uma nova solução simples que veio a mim ontem.


Vamos começar com requisitos simples de senha:


  • deve ter comprimento arbitrário
  • deve consistir em qualquer caractere impresso

import string
import random
from typing import List

def generate_password(length: int) -> str:
     """
     Generate a password of a given `length`.
     """
     result: List[str] = []
     choices = string.printable #    ,    
     while len(result) < length:
         symbol = random.choice(string.printable)
         result.append(symbol)
     return "".join(result)

Nós tentamos:


>>> generate_password(8)
... "1{k]/2)h"
>>> generate_password(13)
... "9ar|&:a+U]Il$"

Bem, a tarefa está concluída, podemos assistir fotos com gatos até o final do dia útil.


Política repentina


, , MyDB . , :


  • 8
  • - (!&? )
  • , bash-

, . :


  • , , -
  • ,


Ok, isso já é complicado, então vamos começar com uma função generate_random_stringque simplesmente gera seqüências aleatórias a partir do que elas deram.


import string
import random
from typing import List

def generate_random_string(length: int, *choices: str) -> str:
    """
    Generate a string of a given `length`.

    The result has at least one symbol from each of `choices` if `length` allows.

    Arguments:
        length -- Result string length.
        choices -- Strings with available symbols.
    """
    if not choices:
        #        ,    
        choices = (string.ascii_letters, ) 

    #      
    all_choices = "".join(choices)
    result: List[str] = []
    choice_index = 0
    while len(result) < length:
        #      , 
        #        
        if choice_index < len(choices):
            symbol = random.choice(choices[choice_index])
            result.append(symbol)
            choice_index += 1
            continue

        #        
        symbol = random.choice(all_choices)
        result.append(symbol)

    #       
    random.shuffle(result)
    return "".join(result)

Então vamos tentar:


>>> #    
>>> generate_random_string(8, string.digits)
... "59197550"
>>> #       
>>> generate_random_string(8, string.ascii_letters, "!") 
... "vIOWXN!o"

Ótimo, é hora de realmente gerar uma senha que atenda a todos os nossos requisitos.


def generate_mydb_password(length: int) -> str:
    """
    Generate a random password for MyDB of a given `length`.

    The result has at least:
    - one uppercase letter
    - one lowercase letter
    - one digit
    - one special character

    Raises:
        ValueError -- If `length` is lesser than 8.
    """
    if length < 8:
        raise ValueError("Password length should be at least 8")

    return generate_random_string(
        length,
        string.ascii_uppercase, #      
        string.ascii_lowercase, #  
        string.digits, #  
        "!&?", #  -,    
    )

Resta apenas verificar:


>>> generate_mydb_password(8)
... "P?P1&7zL"
>>> generate_mydb_password(13)
... "tR!QslK!Sl7EO"
>>> generate_mydb_password(2)
... ValueError: Password length should be at least 8

Total


Escrevemos um gerador de senhas fácil de entender e ao mesmo tempo aleatório, e ainda há muito tempo até o final do dia útil. Se não houver confiança na biblioteca random, você poderá substituí-la pela que desejar.


Obrigado pela atenção!

Source: https://habr.com/ru/post/undefined/


All Articles