正则表达式验证密码强度

我的密码强度准则如下:

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

有人可以给我同样的正则表达式。所有的条件必须符合密码。

167341 次浏览

您可以使用积极的前瞻断言进行这些检查:

^(?=.*[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.

您可以使用零长度正向预测来分别指定每个约束:

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

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

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

  • 易于书写和阅读
  • 易于调试
  • 容易添加/删除部分正则表达式

通常这种方法保持代码 容易维护

说到这里,我分享了一段我在 斯威夫特中编写的代码作为例子:

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 []
}
}
}

我建议加上

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

Codistra 的解决方案工作得很好,但是这个更有效一些: (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)

否定的字符类在一个步骤中消耗所需字符的所有内容,不需要回溯。(点星解决方案工作得很好,但是需要一些回溯。)当然,对于密码之类的短目标字符串,这种效率提高是可以忽略不计的。

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

对于 PHP 来说,这很好用!

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

在这种情况下,结果为真

谢谢@Ridgerunner

另一种解决办法:

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

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

[至少1个大写字符(A-Z) 至少1个小写字符(a-z) 最少1个数字(0-9) 至少一个特殊字符ーー不要忘记把空格也当作特殊字符]

至少10个字符

最多128个字符

一行中不超过2个相同的字符(例如,不允许有111个)

’^ (? ! . < em > (.)1{2}) (? = . [ A-Z ].[0-9]) | (? = . [ a-z ])(? = .[ A-Z ])(? = . [ ^ a-zA-Z0-9]) | (? = .[ A-Z ])(? = . [0-9].[ ^ a-zA-Z0-9]) | (? = . [ a-z ])(? = .[0-9])(? = . * [ ^ a-zA-Z0-9])。{10,127} $’

(? ! . . * (.)1{2})

(? = . [ a-z ])(? = .[ A-Z ])(? = . * [0-9])

(? = . [ a-z ])(? = .[ A-Z ])(? = . * [ ^ a-zA-Z0-9])

(? = . [ A-Z ].[0-9])(? = . * [ ^ a-zA-Z0-9])

(? = . [ a-z ])(? = .[0-9])(? = . * [ ^ a-zA-Z0-9])

。{10.127}

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

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

所以,最佳正则表达式应该是

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

以上正则表达式的最小长度为8。可以将其从{8,}更改为{ 任意数字,}

修改规则?

假设你想要最小 X字符小写字母,字符大写字母,Z字符数字,总最小长度 什么。然后尝试下面的正则表达式

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

注: 在正则表达式中改变 XZ什么

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

编辑2: 添加修改

此外,你亦应考虑将部分规则更改为:

  1. 添加更多特殊字符,例如% 、 ^ 、(、)、-、 _、 + 和句点。我正在添加所有的特殊字符,你错过了上面的数字符号在美国键盘。转义正则表达式使用的。
  2. 将密码设置为8个或更多字符,而不仅仅是一个静态的数字8。

有了上述改进,以及更多的灵活性和可读性,我将把正则表达式修改为。

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

基本解释

(?=(.*RULE){MIN_OCCURANCES,})

每个规则块由(?=(){}).然后,可以轻松地指定规则和出现次数,并在组合之前单独进行测试

详细说明

^                               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