正则表达式验证密码强度


142

我的密码强度标准如下:

  • 8个字符的长度
  • 大写2个字母
  • 1个特殊字符 (!@#$&*)
  • 2个数字 (0-9)
  • 小写3个字母

有人可以请给我正则表达式。必须通过密码满足所有条件。


2
您真的愿意对整个Internet信任密码安全措施吗?
Borealid

12
@Borealid:发布密码策略通常不会严重影响您的安全性。如果是这样,那么你的策略是不好的(“只有passwordhello123有效的密码!”)。
约阿希姆·绍尔

3
@Joachim Sauer:那不是我的意思。我的意思是,发帖人可能只会信任他收到的任何正则表达式。并不是一个好主意。
Borealid

3
实际上,此正则表达式将用于服务代码中,我将测试差异情况而不是盲目地信任它:)
Ajay Kelkar

9
复杂的密码规则通常不会导致使用更安全的密码,重要的只是最小长度。人们无法记住大量的强密码,并且这些规则可能会干扰良好的密码方案。人们可以变得非常有创造力来绕过此类规则,例如通过使用弱密码(例如“ Password-2014”)。通常,您最终会得到较弱的密码,而不是较强的密码。
martinstoeckli 2014年

Answers:


427

您可以使用肯定的前瞻性断言进行以下检查:

^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$

肾小管连结

说明:

^                         Start anchor
(?=.*[A-Z].*[A-Z])        Ensure string has two uppercase letters.
(?=.*[!@#$&*])            Ensure string has one special case letter.
(?=.*[0-9].*[0-9])        Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8}                      Ensure string is of length 8.
$                         End anchor.

92
对于任何想要长度至少为的人n,请替换.{8}.{n,}
NullUserException 2012年

14
+1为完整说明。我的密码规则不同,但是根据您的回答,我可以调整正则表达式。
Morvael 2013年

14
感谢您描述正则表达式中发生的事情。对于那些从未真正了解语法的人来说,这是一个很好的学习示例。

4
我也很欣赏正则表达式的解释。很多时候,我使用发现的复杂正则表达式,但并没有真正了解正在发生的事情。
Nicholas Smith

4
大模式,我想知道为什么不使用量词?至少1个特殊字符,1个数字,1个特殊字符,8个字符:^(?=。*([AZ]){1,})(?=。* [!@ ##&*] {1,})( ?=。* [0-9] {1,})(?=。* [az] {1,})。{8,100} $
RockOnGom

11

您可以使用零长度正向提前查找来分别指定每个约束:

(?=.{8,})(?=.*\p{Lu}.*\p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*\p{Ll}.*\p{Ll})

如果您正则表达式引擎不支持的\p符号和纯ASCII就够了,那么你就可以替换\p{Lu}使用[A-Z],并\p{Ll}[a-z]


8

上面给出的答案是完美的,但我建议使用多个较小的正则表达式,而不要使用较大的正则表达式。
拆分长的正则表达式有一些优点:

  • 易于读写
  • 易于调试
  • 易于添加/删除正则表达式的一部分

通常,这种方法使代码易于维护

话虽如此,我分享了我在Swift中编写的一段代码作为示例:

struct RegExp {

    /**
     Check password complexity

     - parameter password:         password to test
     - parameter length:           password min length
     - parameter patternsToEscape: patterns that password must not contains
     - parameter caseSensitivty:   specify if password must conforms case sensitivity or not
     - parameter numericDigits:    specify if password must conforms contains numeric digits or not

     - returns: boolean that describes if password is valid or not
     */
    static func checkPasswordComplexity(password password: String, length: Int, patternsToEscape: [String], caseSensitivty: Bool, numericDigits: Bool) -> Bool {
        if (password.length < length) {
            return false
        }
        if caseSensitivty {
            let hasUpperCase = RegExp.matchesForRegexInText("[A-Z]", text: password).count > 0
            if !hasUpperCase {
                return false
            }
            let hasLowerCase = RegExp.matchesForRegexInText("[a-z]", text: password).count > 0
            if !hasLowerCase {
                return false
            }
        }
        if numericDigits {
            let hasNumbers = RegExp.matchesForRegexInText("\\d", text: password).count > 0
            if !hasNumbers {
                return false
            }
        }
        if patternsToEscape.count > 0 {
            let passwordLowerCase = password.lowercaseString
            for pattern in patternsToEscape {
                let hasMatchesWithPattern = RegExp.matchesForRegexInText(pattern, text: passwordLowerCase).count > 0
                if hasMatchesWithPattern {
                    return false
                }
            }
        }
        return true
    }

    static func matchesForRegexInText(regex: String, text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}

另外,当使用上述复杂的正则表达式时,很容易遭受灾难性的回溯(regular-expressions.info/catastrophic.html)。直到有一天您的服务器以100%CPU挂起,因为用户使用了“奇怪的”密码,这才引起注意。示例:^([a-z0-9] +){8,} $(您看到错误了吗?)
aKzenT

5

我建议添加

(?!.*pass|.*word|.*1234|.*qwer|.*asdf) exclude common passwords

1

codaddict的解决方案可以正常工作,但是这一解决方案效率更高:(Python语法)

password = re.compile(r"""(?#!py password Rev:20160831_2100)
    # Validate password: 2 upper, 1 special, 2 digit, 1 lower, 8 chars.
    ^                        # Anchor to start of string.
    (?=(?:[^A-Z]*[A-Z]){2})  # At least two uppercase.
    (?=[^!@#$&*]*[!@#$&*])   # At least one "special".
    (?=(?:[^0-9]*[0-9]){2})  # At least two digit.
    .{8,}                    # Password length is 8 or more.
    $                        # Anchor to end of string.
    """, re.VERBOSE)

否定的字符类可在一个步骤中消耗掉多达所需字符的所有内容,需要零回溯。(点星解决方案效果很好,但确实需要一些回溯。)当然,对于较短的目标字符串(例如密码),这种效率提高将是微不足道的。


您能检查一下是否正确吗?我很怀疑,因为在三重双引号和问号之间的第一行中打开了圆括号。我可以看到稍后有Python注释(哈希)。我看不到相应的末端锚点附近的圆括号(美元符号)。应该说我不是正规表达式专家。
lospejos

@lospejos-#不是常规一行注释的开头。此哈希是注释组的一部分,该注释组以a开头,以a (?#结尾)。此正则表达式中没有不平衡的括号。
ridgerunner

1
import re

RegexLength=re.compile(r'^\S{8,}$')
RegexDigit=re.compile(r'\d')
RegexLower=re.compile(r'[a-z]')
RegexUpper=re.compile(r'[A-Z]')


def IsStrongPW(password):
    if RegexLength.search(password) == None or RegexDigit.search(password) == None or RegexUpper.search(password) == None or RegexLower.search(password) == None:
        return False
    else:
        return True

while True:
    userpw=input("please input your passord to check: \n")
    if userpw == "exit":
        break
    else:
        print(IsStrongPW(userpw))

1

@codaddict的解决方案将起作用。

您还应该考虑将某些规则更改为:

  1. 添加更多特殊字符,例如%,^,(,),-,_,+和句点。我要在美国键盘上的数字符号上方添加您遗漏的所有特殊字符。转义正则表达式使用的那些。
  2. 将密码设置为8个或更多字符。不只是静态数字8。

通过上述改进,以及更大的灵活性和可读性,我将正则表达式修改为。

^(?=.*[a-z]){3,}(?=.*[A-Z]){2,}(?=.*[0-9]){2,}(?=.*[!@#$%^&*()--__+.]){1,}.{8,}$

基本说明

(?=.*RULE){MIN_OCCURANCES,}     Each rule block is shown by (){}. The rule and number of occurrences can then be easily specified and tested separately, before getting combined

详细说明

^                             start anchor
(?=.*[a-z]){3,}               lowercase letters. {3,} indicates that you want 3 of this group
(?=.*[A-Z]){2,}               uppercase letters. {2,} indicates that you want 2 of this group
(?=.*[0-9]){2,}               numbers. {2,} indicates that you want 2 of this group
(?=.*[!@#$%^&*()--__+.]){1,}   all the special characters in the [] fields. The ones used by regex are escaped by using the \ or the character itself. {1,} is redundant, but good practice, in case you change that to more than 1 in the future. Also keeps all the groups consistent
{8,}                          indicates that you want 8 or more
$                             end anchor

最后,出于测试目的,这里是带有上述正则表达式的robulink


谢谢@AFract。我在代码中使用它。我喜欢可读性和可重复性,因为您以后必须回头更改它,即在更改密码策略的情况下:)
lsu_guy

0

对于PHP,这很好用!

 if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 
 'CaSu4Li8')){
    return true;
 }else{
    return fasle;
 }

在这种情况下,结果为真

@ridgerunner的思考


为什么不return preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 'CaSu4Li8')呢?
aloisdg移至codidact.com,2018年

0

另一个解决方案:

import re

passwordRegex = re.compile(r'''(
    ^(?=.*[A-Z].*[A-Z])                # at least two capital letters
    (?=.*[!@#$&*])                     # at least one of these special c-er
    (?=.*[0-9].*[0-9])                 # at least two numeric digits
    (?=.*[a-z].*[a-z].*[a-z])          # at least three lower case letters
    .{8,}                              # at least 8 total digits
    $
    )''', re.VERBOSE)

def userInputPasswordCheck():
    print('Enter a potential password:')
    while True:
        m = input()
        mo = passwordRegex.search(m) 
        if (not mo):
           print('''
Your password should have at least one special charachter,
two digits, two uppercase and three lowercase charachter. Length: 8+ ch-ers.

Enter another password:''')          
        else:
           print('Password is strong')
           return
userInputPasswordCheck()

0

密码必须满足以下4个复杂度规则中的至少3个,

[至少1个大写字母(AZ)至少1个小写字母(az)至少1个数字(0-9)至少1个特殊字符-不要忘记将空格也视为特殊字符]

至少10个字符

最多128个字符

连续不超过2个相同字符(例如,不允许111个字符)

'^(?!。(。)\ 1 {2})((?=。 [az])(?=。[AZ])(?=。 [0-9])|(?=。[az] )(?=。 [AZ])(?=。[^ a-zA-Z0-9])|(?=。 [AZ])(?=。[0-9])(?=。 [^ a -zA-Z0-9])|(?=。[az])(?=。 [0-9])(?=。* [^ a-zA-Z0-9])))。{10,127} $'

(?!。*(。)\ 1 {2})

(?=。[az])(?=。 [AZ])(?=。* [0-9])

(?=。[az])(?=。 [AZ])(?=。* [^ a-zA-Z0-9])

(?=。[AZ])(?=。 [0-9])(?=。* [^ a-zA-Z0-9])

(?=。[az])(?=。 [0-9])(?=。* [^ a-zA-Z0-9])

。{10.127}


0

不幸的是,上述所有正则表达式都不适用于我。强密码的基本规则是

  • 至少应包含一个大写字母
  • 至少应包含一个小写字母
  • 应至少包含一个数字
  • 至少应包含一个特殊字符
  • 和最小长度

因此,最佳正则表达式将是

^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*]).{8,}$

上面的正则表达式的最小长度为8。您可以将其从{8,}更改为{ any_number,}

修改规则?

假设您要最少x个字符的小写字母,y个字符的大写字母,z个字符的数量,总最小长度w。然后尝试下面的正则表达式

^(?=.*[a-z]{x,})(?=.*[A-Z]{y,})(?=.*[0-9]{z,})(?=.*[!@#\$%\^&\*]).{w,}$

注意:在正则表达式中更改xyzw

编辑:更新正则表达式答案

Edit2:添加了修改


您的正则表达式匹配吗?12345678确定它是一个密码吗?请在发布前尝试使用正则表达式。
托托

更好,但是不能回答问题,他们想要1)8个字符的长度。2)2个字母大写。3)1个特殊字符(!@#$&*)。4)2个数字(0-9)。5)3个小写字母。
Toto

@Toto您现在可以分享您的想法吗?
朱德·哈特里

您的正则表达式未考虑2个强制性大写字母可以与其他字符分开的情况,小写字母和数字的相同备注。有效答案是已被接受的答案。
Toto
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.