简体   繁体   English

编写代码以检查密码是否符合特定条件

[英]Writing code to check if a password meets certain criteria

I am trying to write a function in Python that checks a password and returns True or False based on the following criteria:我正在尝试在 Python 中编写一个 function 来检查密码并根据以下标准返回 True 或 False:

  • it must be at least 8 characters long它必须至少有 8 个字符长
  • it must contain at least one capital letter它必须至少包含一个大写字母
  • it must contain at least one lower case letter它必须包含至少一个小写字母
  • it must contain at least one number它必须包含至少一个数字
  • it must contain at least one of the following special characters: ;@#$%&()-_[]{}:',".?/<>, The twist is that it MUST NOT contain special characters other than the ones listed. eg, a space. ~ or * or anything else.它必须至少包含以下特殊字符之一:;@#$%&()-_[]{}:',".?/<>, 扭曲的是它不得包含除这些字符之外的特殊字符列出。例如,空格。~ 或 * 或其他任何内容。

I have been trying to come up with code for a week now and have tried different variations of the following:我已经尝试了一周的代码,并尝试了以下不同的变体:

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

But the code does not work as intended because if there are, for example, only lower case letters it returns True.但是代码不能按预期工作,因为例如,如果只有小写字母,它会返回 True。 So I tried the following:所以我尝试了以下方法:

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

But it doesn't return False when an invalid character is used (eg ~).但是当使用无效字符(例如~)时,它不会返回 False。 The function calls below should return True, True, False, False, False, True, False and False.下面的 function 调用应返回 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'))

I will be most grateful if anyone points me in the right direction.如果有人指出我正确的方向,我将不胜感激。

The issue here is that on the occasion that any rule is true, it returns true.这里的问题是,在任何规则为真的情况下,它都会返回真。 But what you want is for it to check that all rules are true.但是您想要的是它检查所有规则是否正确。 To do this, we'll need to make four different variables, one for each condition:为此,我们需要创建四个不同的变量,每个条件一个:

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

I tested this and it gave me these results:我对此进行了测试,它给了我以下结果:

True
True
False
False
False
True
False
False

Note the last line there,注意最后一行,

return hs and hn and hu and hl

This is basically shorthand for saying this:这基本上是这样说的简写:

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

By the way, this is a really useful password checker, might come in handy one day!顺便说一句,这是一个非常有用的密码检查器,也许有一天会派上用场!

Without steering you towards a rewrite (which IS a good idea) but only answering your direct question...无需引导您进行重写(这是一个好主意),而仅回答您的直接问题...

You are not checking for "the twist", the case where the password contains an invalid character.您没有检查“扭曲”,即密码包含无效字符的情况。 To do that, you need to add one more test to your conditional:为此,您需要在条件中再添加一项测试:

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

which says that ALL characters in the password must be in one of the valid ranges of characters.这表示密码中的所有字符都必须在有效的字符范围之一内。 If you add this, you get the output you desire.如果你添加这个,你会得到你想要的 output。

The full solution, including another minor fix, looks like this then:完整的解决方案,包括另一个小修复,如下所示:

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

and produces:并产生:

True
True
False
False
False
True
False
False

You can use this code, it also tells you why the password is incorrect.您可以使用此代码,它还会告诉您密码不正确的原因。 Simple if and else conditions.简单的 if 和 else 条件。 But I would prefer if you use RegEx Python但如果你使用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

Firt off, please don't define a variable called list (or int or str for that matter) as this is a reserved word and a built-in function.首先,请不要定义名为list (或intstr )的变量,因为这是保留字和内置 function。 Then, you don't need a nested if-block but just a boolean value that gets set to False if any of the conditions is not met.然后,您不需要嵌套的 if 块,只需要一个 boolean 值,如果不满足任何条件,该值将设置为False You can check the conditions independently:您可以独立检查条件:


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

By checking each condition subsequently, you don't have to nest your conditions and can detect the exact problem of the password.通过随后检查每个条件,您不必嵌套条件并且可以检测密码的确切问题。 You don't need to print them, of course, but this might help in debugging and testing for specific violations.当然,您不需要打印它们,但这可能有助于调试和测试特定的违规行为。

Try this:尝试这个:

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

I feel validating each condition step by step is a better approach to avoid confusions.我觉得逐步验证每个条件是避免混淆的更好方法。 This way we can let the user know what mistake they are committing to correct, rather than to just say if a password is valid or not.通过这种方式,我们可以让用户知道他们正在纠正什么错误,而不仅仅是说密码是否有效。 Checking the password length and disallowed punctuation will be better ones to start validation.检查密码长度和不允许的标点符号将更好地开始验证。

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

Test Cases测试用例

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

Result结果

True True False False False True False False真 真 假 假 假 真 假 假

I have updated my answer and made it a bit simpler for you to understand.我已经更新了我的答案,让你更容易理解。 Let me know if this is easier to follow through.让我知道这是否更容易完成。 The whole program loops through the string only once while checking for everything needed.整个程序只在字符串中循环一次,同时检查所有需要的东西。 That way you don't have looping thru many times.这样你就不会循环多次。

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

The output for this will be as follows. output 如下。 I ran it multiple times:我多次运行它:

Password :thisisnotagoodpassword
Invalid Password

Password :thisis notaG00dPassw0#d
Invalid Password

Password :thisisaG00dPassw0$d
Valid Password

Password :Abcd123$
Valid Password

Password :Abc123$
Invalid Password

How to convert this to a Function:如何将其转换为 Function:

You can always replace the print statement with a return True or return False statement when you convert this code into a function.当您将此代码转换为 function 时,您始终可以将 print 语句替换为 return True 或 return False 语句。 Then use the def to create.然后使用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')

To call the function, you can do:要调用 function,您可以:

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

That will return the value of True or False to check.这将返回TrueFalse的值进行检查。

Hopefully it was helpful for you to understand the implementation.希望对您理解实现有所帮助。

I think using regular expression library "re" is the best way of doing this.我认为使用正则表达式库“re”是最好的方法。 so simple, so clean.如此简单,如此干净。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM