Python regex pour faire correspondre 3 caractères consécutifs dans l'alphabet mais pas nécessairement côte à côte
Je dois construire une fonction python qui utilise regex pour vérifier la complexité d'un mot de passe qui doit avoir au moins 8 caractères, contenir des chiffres, des lettres et des symboles spéciaux et dernières règles (les plus difficiles): ne pas contenir trois lettres consécutives ou trois chiffres consécutifs. Pour illustrer la dernière règle: Mz2a%yc98B
ne sera pas acceptée car elle contient 3 lettres consécutives: aBc
J'ai bien fait pour les deux premières règles mais je n'ai aucune idée de ce que je peux faire pour la dernière règle. C'est assez complexe je pense. Certaines personnes m'ont dit que c'était impossible de faire ça avec regex mais en fait ça doit être possible ou mon professeur est fou?
Merci beaucoup!
Mon code pour l'instant:
import re
pattern = re.compile(r"")
while True:
password = input("Enter your password")
if re.match(r"(?=.*[a-z])(?=.*[A-Z])(?=(.*[!%@$#&^*()\-__+.]){1,})(?=.*[0-9]).{8,}", password):
result = pattern.match(password)
print("Your password is strong enough")
else:
print("Your password is not strong enough")
Et aussi dans l'exemple de mot de passe que j'ai donné oui, ils sont aBc, le B est le dernier caractère. Et ce n'est qu'un exemple. Quand je veux dire consécutifs, je veux dire consécutifs dans l'alphabet. Si par exemple les lettres efg sont utilisées même étalées dans le mot de passe, il doit le détecter. Merci
Solution du problème
Voici une solution au troisième critère de votre problématique.
import string
from more_itertools import windowed
alphabet = string.ascii_lowercase
numbers = string.digits
passwords = ["Mz2a%yc98B", "a1b2g3D!", "Tr0ub4dor?"]
def find_triplets(charset: set, target: str) -> bool:
if len(charset) < 3:
return False
else:
chars = "".join(sorted(charset))
triplets = ["".join(tpl) for tpl in windowed(chars, 3)]
return any(triplet in target for triplet in triplets)
for pwd in passwords:
# we use sets to get rid of duplicatess
alpha = set()
nums = set()
for char in pwd:
if char.isalpha():
alpha.add(char.lower())
elif char.isdigit():
nums.add(char)
else:
pass # we don't care about symbols here
if find_triplets(alpha, alphabet) or find_triplets(nums, numbers):
print(f"Your password {pwd} contains 3 consecutive letters or numbers")
else:
print(f"Your password {pwd} is good enough, I guess")
Après le code de configuration, nous définissons d'abord une fonction pour générer des chaînes de 3 caractères ( triplets
) à partir de l'entrée charset
, après qu'elle ait été triée et transformée en une chaîne elle-même. Cela utilise la fonction du module windowed()
tiers très utile. more_itertools
La fonction retourne True
si elle trouve des triplets qui correspondent à une séquence consécutive dans la target
chaîne, et False
si ce n'est pas le cas. Assez simple.
Ensuite, nous parcourons notre liste de mots de passe (que vous avez utilisés input()
dans votre code, ce qui est bien). Tout d'abord, nous parcourons la chaîne de mot de passe caractère par caractère et les ajoutons à l'ensemble approprié (en minuscules dans le cas de caractères alphabétiques). Nous appelons ensuite notre find_triplets()
fonction pour tester des suites consécutives de lettres ou de chiffres, et imprimons un message en conséquence.
Vous voudrez évidemment changer certains de ces éléments pour les adapter à votre mission, mais je vous laisse le soin de le faire.
Il existe une autre méthode utilisant re.search()
, mais je pense que any(triplet in target for triplet in triplets)
c'est beaucoup plus Pythonic.
Commentaires
Enregistrer un commentaire