【发布时间】:2015-04-29 02:17:04
【问题描述】:
我正在尝试在 PHP 中编写一个正则表达式,以确保密码符合以下条件:
- 至少应包含 8 个字符
- 应至少包含一个特殊字符
- 应至少包含一个大写字母。
我写了如下表达式:
$pattern=([a-zA-Z\W+0-9]{8,})
但是,它似乎无法按照列出的标准工作。请问我可以再找一双眼睛来帮助我吗?
【问题讨论】:
我正在尝试在 PHP 中编写一个正则表达式,以确保密码符合以下条件:
我写了如下表达式:
$pattern=([a-zA-Z\W+0-9]{8,})
但是,它似乎无法按照列出的标准工作。请问我可以再找一双眼睛来帮助我吗?
【问题讨论】:
您的正则表达式 - ([a-zA-Z\W+0-9]{8,}) - 实际上在至少 8 个字符长的较大文本中搜索子字符串,但也允许任何英文字母、非单词字符([a-zA-Z0-9_] 除外)和数字,所以它不强制执行您的 2 个要求。可以使用look-aheads 进行设置。
这是一个固定的正则表达式:
^(?=.*\W.*)(?=.*[A-Z].*).{8,}$
实际上,如果您还想匹配/允许非英文字母,您可以将[A-Z] 替换为\p{Lu}。您还可以考虑使用\p{S} 而不是\W,或者通过添加符号或字符类来进一步精确您的special character 标准,例如[\p{P}\p{S}](这也将包括所有 Unicode 标点符号)。
增强的正则表达式版本:
^(?=.*[\p{S}\p{P}].*)(?=.*\p{Lu}.*).{8,}$
人类可读的解释:
^ - 字符串的开头(?=.*\W.*) - 要求至少有 1 个非单词字符
(?=.*[\p{S}\p{P}].*) - 至少 1 个 Unicode 特殊符号或标点符号 (?=.*[A-Z].*) - 要求至少有 1 个大写英文字母
(?=.*\p{Lu}.*) - 至少 1 个 Unicode 字母.{8,} - 要求至少 8 个符号$ - 字符串结束见Demo 1和Demo 2 (Enhanced regex)
示例代码:
if (preg_match('/^(?=.*\W.*)(?=.*[A-Z].*).{8,}$/u', $header)) {
// PASS
}
else {
# FAIL
}
【讨论】:
使用正数 lookahead ?= 我们确保满足所有密码要求。
至少 8 个字符长
至少 1 个大写字母
至少 1 个特殊字符
^((?=[\S]{8})(?:.*)(?=[A-Z]{1})(?:.*)(?=[\p{S}])(?:.*))$
if (preg_match('/^((?=[\S]{8})(?:.*)(?=[A-Z]{1})(?:.*)(?=[\p{S}])(?:.*))$/u', $password)) {
# Strong Password
} else {
# Weak Password
}
12345678 - WEAK
1234%fff - WEAK
1234_44A - WEAK
133333A$ - STRONG
^ assert position at start of the string
1st Capturing group ((?=[\S]{8})(?:.*)(?=[A-Z]{1})(?:.*)(?=[\p{S}])(?:.*))
(?=[\S]{8}) Positive Lookahead - Assert that the regex below can be matched
[\S]{8} match a single character present in the list below
Quantifier: {8} Exactly 8 times
\S match any kind of visible character [\P{Z}\H\V]
(?:.*) Non-capturing group
.* matches any character (except newline) [unicode]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?=[A-Z]{1}) Positive Lookahead - Assert that the regex below can be matched
[A-Z]{1} match a single character present in the list below
Quantifier: {1} Exactly 1 time (meaningless quantifier)
A-Z a single character in the range between A and Z (case sensitive)
(?:.*) Non-capturing group
.* matches any character (except newline) [unicode]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?=[\p{S}]) Positive Lookahead - Assert that the regex below can be matched
[\p{S}] match a single character present in the list below
\p{S} matches math symbols, currency signs, dingbats, box-drawing characters, etc
(?:.*) Non-capturing group
.* matches any character (except newline) [unicode]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
$ assert position at end of the string
u modifier: unicode: Pattern strings are treated as UTF-16. Also causes escape sequences to match unicode characters
【讨论】: