Réécriture du générateur de mots de passe

Politique de mot de passe


Des mots de passe hors de la politique


J'ai le sentiment d'avoir déjà écrit cinq fois une fonction pour générer des mots de passe. Et il le faisait différemment à chaque fois. Et la raison en est les différentes exigences de mot de passe pour différents projets et outils. Il n'y aura pas de code complexe, juste un résumé d'une nouvelle solution simple qui m'est venue hier.


Commençons par des exigences de mot de passe simples:


  • doit être de longueur arbitraire
  • doit comprendre tous les caractères imprimés

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)

Nous essayons:


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

Eh bien, la tâche est terminée, nous pouvons regarder des photos avec des chats jusqu'à la fin de la journée de travail.


Politique soudaine


, , MyDB . , :


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

, . :


  • , , -
  • ,


D'accord, c'est déjà compliqué, alors commençons par une fonction generate_random_stringqui va simplement générer des chaînes aléatoires à partir de ce qu'elles ont donné.


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)

Essayons donc:


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

Génial, il est temps de générer un mot de passe qui réponde à toutes nos exigences.


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, #  
        "!&?", #  -,    
    )

Il ne reste plus qu'à vérifier:


>>> 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


Nous avons écrit un générateur de mots de passe facile à comprendre et en même temps plutôt aléatoire, et il reste encore beaucoup de temps jusqu'à la fin de la journée de travail. S'il n'y a aucune confiance dans la bibliothèque random, vous pouvez la remplacer par celle que vous aimez.


Merci pour l'attention!

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


All Articles