有没有办法只在满足 3/4 条件的情况下检查密码的有效性?

Is there a way to check the validity of a password only if 3/4 conditions are met?

我必须编写一个程序来检查密码的有效性。 条件是:至少 8 个字符,1 个大写字母,1 个小写字母,1 个 0-9 范围内的数字,1 个符号。 如果满足 3 / 4 个条件(不包括密码长度,因为它应该总是长于 8 个字符)程序应该检查密码强度。 如果密码长度为 8 个字符,则强度等于 1。每增加 4 个字符,强度就会增加 1。 条件都满足的话,实力应该翻倍

在下面的代码中,我写了一大行代码,但我认为我有一个错误,并且有一种更快的方法来完成它。 所以我问你是否有办法更快地做到这一点。如果是,那会是什么?

def is_valid_password():
    pwd=input("Enter a password: ")
    f=1
    l=0
    u=0
    d=0
    s=0
    p=0
    if(len(pwd)>=8):
        for i in pwd:
            if i.islower():
                l+=1
            if i.isupper():
                u+=1
            if i.isdigit():
                d+=1
            if(i=='!' or i=='@' or i=='#' or i=='$' or i=='&' or i=='_'):
                s+=1
    if((l+u+d+s)==len(pwd) and l==0 and u>=1 and d>=1 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u==0 and d>=1 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d==0 and s>=1) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s==0) or ((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s>=1):
        if((l+u+d+s)==len(pwd) and l>=1 and u>=1 and d>=1 and s>=1):
            if(len(pwd)>12):
                f=(f+(len(pwd)-8)//4)*2
            elif(len(pwd)>=9 and len(pwd)<=12):
                f==4
            elif(len(pwd)==8):
                f==2
            print(f"Valid password with strength {f}")        
        else:
            if(len(pwd)>12):
                f=f+(len(pwd)-8)//4
            elif(len(pwd)>=9 and len(pwd)<=12):
                f==2
            elif(len(pwd)==8):
                f==1
            print(f"Valid password with strength {f}")
            
    else:
        print("Invalid password!")
 
while True:
    is_valid_password()

我可能会列一个函数列表,例如 testLength()testUpper()testDigit() 等。这些函数只是 return 一个 1(完成)或 0(失败)。请注意,扩展测试的数量和种类真的很容易。

现在你可以这样写

numPassed = testLength(pwd) + \
            testUpper(pwd) + \
            testDigit(pwd) + ...
if (numPassed < (3 * numTests)/4)
    issueError("password too weak")

这是一种伪代码,但我认为这个想法是可以理解的。 请注意,此代码当然不会更快,但它易于理解且易于维护或扩展。 (它也不慢,只要你不想一次测试十亿个密码)。

就个人而言,我这样做:

import re
from math import ceil

def is_valid_password(PassWord):
    Conditions = 0
    
    if len(PassWord) < 8:
        print(f"The password ({PassWord}) is too short !")
        return 0
    
    # Or re.findall("[a-z]", PassWord):
    if PassWord != PassWord.lower():
        Conditions += 1
    
    # Or re.findall("[A-Z]", PassWord):
    if PassWord != PassWord.upper():
        Conditions += 1
    
    if re.findall("[0-9]", PassWord):
        Conditions += 1
    
    # Or re.findall("[!@#$&_]", PassWord):
    if re.findall("[^a-zA-Z0-9]", PassWord):
        Conditions += 1
    
    if Conditions < 3:
        print(f"The password ({PassWord}) not respect the conditions !")
        return 0
    
    # Or Power = 1 + ceil((len(PassWord) - 8) / 4) 
    # if you want :
    # 8 char = 1
    # 9-12 char = 2
    # 13-16 char = 3
    Power = 1 + int((len(PassWord) - 8) / 4)
    
    if Conditions == 4:
        Power *= 2
    
    print(f"Valid password ({PassWord}) with strength {Power}") 
    return 1


is_valid_password("Hello") # Error
is_valid_password("hello2020") # Error
is_valid_password("HELLO2020") # Error
is_valid_password("Hello2022") # 1
is_valid_password("Hello 2022") # 2
is_valid_password("HelloHello2022") # 2
is_valid_password("Hello _ 2022") # 4
is_valid_password("Hello Hello 2022") # 6

我想它更简单,更易读。

您可以使用正则表达式尝试这种方式。 包括您需要在括号中和模式中找到的内容:

passwd='P%&ippo8lo'
pattern=r'(\d)|([[:upper:]])|([[:lower:]])|([$%&])'

1 位数字,2 个大写字母,3 个小写字母,4 个符号

'findall' 方法将 return 一个集合列表,您只需确保其中的所有字段都已被使用:

rt=regex.findall(pattern, passwd)
[
 ('', 'P', '', '')
 ('', '', '', '%')
 ('', '', '', '&')
 ('', '', 'i', '')
 ('', '', 'p', '')
 ('', '', 'p', '')
 ('', '', 'o', '')
 ('8', '', '', '')
 ('', '', 'l', '')
 ('', '', 'o', '')
]

现在密码的难易程度取决于使用了多少组字段:

good = [False] * 4

for s in rt:
    for i in range(0, len(s)):
        if s[i] != '':
            good[i] = True

print(good)

[True, True, True, True]

如果其中一个请求没有被使用过,对应的字段将为False

关于密码长度:

ovr_len = len(password) - 8
hardness_point = int(ovr_len / 4)
total_point += hardness_point

8字以上每4个字得一分