【问题标题】:Writing code to check if a password meets certain criteria编写代码以检查密码是否符合特定条件
【发布时间】:2020-12-08 08:15:40
【问题描述】:

我正在尝试用 Python 编写一个函数来检查密码并根据以下条件返回 True 或 False:

  • 长度必须至少为 8 个字符
  • 必须至少包含一个大写字母
  • 必须至少包含一个小写字母
  • 必须至少包含一个数字
  • 它必须至少包含以下特殊字符之一:!@#$%&()-_[]{};':",./? 扭曲的是,它不得包含除所列字符之外的特殊字符,例如空格、~ 或 * 或其他任何内容。

我已经尝试编写代码一周了,并尝试了以下不同的变体:

def password_check(str):
    list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
    estr = True
    if len(str) >= 8:
        for i in str:
            if i in list:
                estr = True
            else:
                if i.isnumeric():
                    estr = True
                else:
                    if i.isupper():
                        estr = True
                    else:
                        if i.islower():
                            estr = True
                        else:
                            return False
    else:
        estr = False
    return estr

但是代码不能按预期工作,因为例如,如果只有小写字母,它会返回 True。所以我尝试了以下方法:

def password_check(str):
    list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
    if any(i.isupper() for i in str) and any(i.islower() for i in str) and any(i.isdigit() for i in str) and len(str) >= 8 and any(i in list for i in str):
        estr = True
    else:
        return False

但当使用无效字符(例如 ~)时,它不会返回 False。下面的函数调用应该返回 True、True、False、False、False、True、False 和 False。

print(password_check("tHIs1sag00d.p4ssw0rd."))
print(password_check("3@t7ENZ((T"))
print(password_check("2.shOrt"))
print(password_check("all.l0wer.case"))
print(password_check("inv4l1d CH4R4CTERS~"))
print(password_check('X)ndC@[?/fVkoN/[AkmA0'))
print(password_check(':>&BhEjGNcaSWotpAy@$tJ@j{*W8'))
print(password_check('ZW}VoVH.~VGz,D?()l0'))

如果有人指出我正确的方向,我将不胜感激。

【问题讨论】:

  • Link这个回答你的问题?
  • 尝试将您的代码重组为if ... elif ... elif ... 链并否定所有条件,以便您有机会在返回 False 之前打印一条条件失败的消息。然后你也可以使用调试器

标签: python password-checker


【解决方案1】:

这里的问题是,当 any 规则为真时,它返回真。但你想要的是它检查 all 规则是否为真。为此,我们需要创建四个不同的变量,每个条件一个:

def password_check(str):
    list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
    hs = False # Has Symbols
    hn = False # Has Numbers
    hu = False # Has Uppercase
    hl = False # Has Lowercase
    if len(str) >= 8:
        for i in str:
            if i in list:
                hs = True
            elif i.isnumeric():
                hn = True
            elif i.isupper():
                hu = True
            elif i.islower():
                hl = True
            else:
                return False
    else:
        return False
    return hs and hn and hu and hl

我对此进行了测试,它给了我以下结果:

True
True
False
False
False
True
False
False

注意最后一行,

return hs and hn and hu and hl

这基本上是这样说的简写:

if not hs:
    return False
if not hn:
    return False
if not hu:
    return False
if not hl:
    return False
return True

顺便说一句,这是一个非常有用的密码检查器,也许有一天会派上用场!

【讨论】:

  • 感谢 Kettle3D 的回答。它的简单很漂亮,这是我的第一个方法。我无法完全破解它,因为我错过了你指出的最后一行。
【解决方案2】:

无需引导您进行重写(这是个好主意),而仅回答您的直接问题...

您没有检查“扭曲”,即密码包含无效字符的情况。为此,您需要在条件中再添加一项测试:

and all((i.isupper() or i.islower() or i.isdigit() or i in list) for i in str)

表示密码中的所有字符都必须在有效字符范围之一内。如果你添加这个,你会得到你想要的输出。

完整的解决方案,包括另一个小修复,如下所示:

def password_check(str):
    list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>',
            '?']
    if any(i.isupper() for i in str) and any(i.islower() for i in str) and any(i.isdigit() for i in str) and len(
            str) >= 8 and any(i in list for i in str) and all((i.isupper() or i.islower() or i.isdigit() or i in list) for i in str):
        return True
    else:
        return False

并产生:

True
True
False
False
False
True
False
False

【讨论】:

  • 谢谢史蒂夫。我尝试使用'all(...)' 表达式,但我认为我弄错了括号。你的回答让我明白了这一点。
【解决方案3】:

您可以使用此代码,它还会告诉您密码不正确的原因。简单的 if 和 else 条件。但我更喜欢你使用RegEx Python

def password_check(password):

    SpecialSym = ['!', '@', '#', '$', '%', '&',
                  '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']

    if len(password) < 8:
        print('length should be at least 6')
        return False

    if not any(char.isdigit() for char in password):
        print('Password should have at least one numeral')
        return False

    if not any(char.isupper() for char in password):
        print('Password should have at least one uppercase letter')
        return False

    if not any(char.islower() for char in password):
        print('Password should have at least one lowercase letter')
        return False

    if not any(char in SpecialSym for char in password):
        print('Password should have at least one of the symbols $@#')
        return False

    for i in password:
        if not (('0' <= i <= '9') or ('a' <= i.lower() <= 'z')):
            # Special Char
            if i not in SpecialSym:
                return False

    return True

【讨论】:

    【解决方案4】:

    首先,请不要定义名为list(或intstr)的变量,因为这是保留字和内置函数。然后,您不需要嵌套的 if 块,而只需要一个布尔值,如果不满足任何条件,则设置为 False。您可以独立检查条件:

    
    def password_check(p):
        print('\nchecking password: ',p)
        chlist = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
        good_password = True ## Set to true and try to disprove
    
        nums = False
        letters = False
        special = False
    
        for c in p:
            if not (c.isalnum() or c in chlist):
                good_password = False
                print("Invalid character: "+c)
            elif c.isdigit():
                nums = True
            elif c.isalpha():
                letters = True
            elif c in chlist:
                special = True
        if not letters:
            good_password = False
            print("There are no letters")
        if not nums:
            good_password = False
            print("There are no numbers")
        if not special:
            good_password = False
            print("There are no special characters")
        if p == p.lower() or p==p.upper():
            good_password = False
            print("Please use upper and lower case letters")
        if len(p) < 8:
            good_password = False
            print("Too short")
    
        return good_password
    

    通过随后检查每个条件,您不必嵌套条件并且可以检测密码的确切问题。当然,您不需要打印它们,但这可能有助于调试和测试特定违规行为。

    【讨论】:

      【解决方案5】:

      试试这个:

      import string 
      sc = "!@#$%&()-_[]{};:,./<>?"
      uc = string.ascii_uppercase
      lc = uc.lower()
      num = string.digits
      
      def password_checker(password):
           if len(password) >= 8:
             sn = 0 #numbers of special character
             un = 0 #......... uppercase letters
             ln = 0 #........ lowercase 
             dn = 0 #.........digits
             for i in password:
                 if i in uc:
                    un += 1
                 elif i in lc:
                    ln += 1
                 elif i in num:
                   dn += 1
                 elif i in sc and sn == 0:
                   sn += 1
                 else:
                   break
             else:
                   print("Valid Password")
           else:
              print("Invalid Password")   
      
      
      
      password_checker(input()) 
      

      【讨论】:

        【解决方案6】:

        我觉得逐步验证每个条件是避免混淆的更好方法。通过这种方式,我们可以让用户知道他们正在纠正什么错误,而不仅仅是说密码是否有效。检查密码长度和不允许的标点将是更好的开始验证。

        import re
        
        
        def password_check(password):
            return_value = True
        
            if len(password) < 8:
                # print('Password length is less than 8 characters')
                return_value = False
        
            punctuation_not_allowed = '[\s+*+=\^`|~]'
            if re.search(punctuation_not_allowed, password):
                # print(f'Whitespaces or punctuations "*+=\^`|~" is not allowed')
                return_value = False
        
            if not any(char.isupper() for char in password) or \
                    not any(char.islower() for char in password) or \
                    not any(char.isdigit() for char in password):
                # print('Password requires at least one upper case letter, one lower case letter and one digit')
                return_value = False
        
            if not re.search(r"""[!@#$%&()\-_\[\]{};':",./<>?]""", password):
                # print("""At least special char in "[!@#$%&()-_[]{};':",./<>?]" is required""")
                return_value = False
        
            return return_value
        

        测试用例

        print(password_check("tHIs1sag00d.p4ssw0rd."))
        print(password_check("3@t7ENZ((T"))
        print(password_check("2.shOrt"))
        print(password_check("all.l0wer.case"))
        print(password_check("inv4l1d CH4R4CTERS~"))
        print(password_check('X)ndC@[?/fVkoN/[AkmA0'))
        print(password_check(':>&BhEjGNcaSWotpAy@$tJ@j{*W8'))
        print(password_check('ZW}VoVH.~VGz,D?()l0'))
        

        结果

        真真假假假真假假

        【讨论】:

          【解决方案7】:

          我已经更新了我的答案,让你更容易理解。让我知道这是否更容易完成。整个程序只在字符串中循环一次,同时检查所有需要的东西。这样你就不会循环多次。

          pwd = input('Password :')
          
          #set uppercase, lowercase, digits, special to False
          #if password has these, then set to True
          
          ucase = lcase = digit = scase = False
          
          #for loop when applied to a string will pick each char for processing
          #this will allow you to  check for conditions on the char
          
          for ch in pwd:
          
              #check if char is uppercase, set ucase to True
          
              if ch.isupper(): ucase = True
          
              #check if char is lowercase, set lcase to True
          
              elif ch.islower(): lcase = True
          
              #check if char is a number, set digit to True
          
              elif ch.isdigit(): digit = True
          
              #check if char is special char, set scase to True
              #by using in (...), it checks against each item in the list
          
              elif ch in ('!@#$%&()-_[]{};\':",./<>?'): scase = True
          
              #if it is not one of these, then it is not valid password
              else:
                  break
          
          #check if everything is true
          
          if len(pwd) >= 8 and ucase and lcase and digit and scase:
              print ('Valid Password')
          else:
              print ('Invalid Password')
          

          输出如下。我运行了多次:

          Password :thisisnotagoodpassword
          Invalid Password
          
          Password :thisis notaG00dPassw0#d
          Invalid Password
          
          Password :thisisaG00dPassw0$d
          Valid Password
          
          Password :Abcd123$
          Valid Password
          
          Password :Abc123$
          Invalid Password
          

          如何将其转换为函数:

          当您将此代码转换为函数时,您始终可以将 print 语句替换为 return True 或 return False 语句。然后使用def创建。

          def pword(pwd):
              #the whole code from #set uppercase... (except first line)
              #to the final if statement
              #if you want to return True or False, you can use
              #return True instead of print ('Valid Password')
          

          要调用该函数,你可以这样做:

          check = pword(input('Password. :'))
          

          这将返回 TrueFalse 的值进行检查。

          希望它对您了解实现有所帮助。

          【讨论】:

          • 谢谢乔·芬兹。一个非常有趣的方法。我只是一个初学者 Python 编码器,所以我不熟悉你构建条件的方式。感谢您帮助我学习。
          • @Tom,我刚回去复习了。看起来我的代码中有一个小错误。我会修复并重新发布。也将尝试呈现一个初学者的版本。这样你就可以理解实现了。
          • @Tom, I. 修复了代码并删除了旧代码。而是以易于理解的方式编写代码。
          【解决方案8】:

          我认为使用正则表达式库“re”是最好的方法。如此简单,如此干净。

          import re
          
          while True:
              p = input('enter a new password: ')
              if (len(p) < 6 or len(p)>16):
                  print('Your password should be between 6-16 characters.')
              
              elif not re.search("[A-Z]", p):
                  print('Your password should include at least one capital letter.')
                  
              elif not re.search('[a-z]', p):
                  print('Your password should include at least one letter.')
          
              elif not re.search('[0-9]', p):
                  print('Your password should include at least one number.')
          
              elif not re.search('[@#$%]', p):
                  print('Your password should include at least one of these signs: @#$%')
              
              else:
                  print('Your password is valid.')
                  break
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-11-16
            • 2023-03-27
            • 2019-12-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-12
            相关资源
            最近更新 更多