PHP正则表达式用于密码验证

4

我的脚本没有达到预期的效果。我希望密码包含 A-Z、a-z、0-9 和特殊字符。

  • A-Z
  • a-z
  • 大于等于 2 个 0-9
  • 大于等于 2 个特殊字符
  • 字符串长度大于等于 8

所以我想强制用户使用至少 2 位数字和至少 2 位特殊字符。我的脚本可以实现,但是强制我将数字或字符连续使用。我不想要这样。例如,密码 testABC55$$ 是有效的 - 但我不想要这个。

相反我想要 test$ABC5#8 也是有效的。所以基本上数字/特殊字符可以相同或不同 -> 但必须在字符串中分开使用。

PHP 代码:

$uppercase = preg_match('#[A-Z]#', $password);
$lowercase = preg_match('#[a-z]#', $password);
$number    = preg_match('#[0-9]#', $password);
$special   = preg_match('#[\W]{2,}#', $password); 
$length    = strlen($password) >= 8;

if(!$uppercase || !$lowercase || !$number || !$special || !$length) {
  $errorpw = 'Bad Password';

好的,那段代码有什么问题? - Oliver Charlesworth
我很确定,你可以将这个合并成一个正则表达式。 - user267885
代码可以运行,但效果不是预期的。请注意上面我的密码示例。 - MrPizzaFace
我只是强制用户创建更安全的密码。Dagon,我怎么“阻止”你了?我没有看到问题。在我看来,你可能有一个较弱的“首选密码”。 - MrPizzaFace
简单的答案是,不要使用正则表达式。正则表达式并不是为了做这个而设计的,你需要花费大量的精力来扭曲它的本意,而这些精力可以用来轻松地创建一个更有效的解决方案。 - Kendall Frey
3个回答

12

使用可读性较好的格式(可以进行优化以缩短长度),因为您是正则表达式新手>>

^(?=.{8})(?=.*[A-Z])(?=.*[a-z])(?=.*\d.*\d.*\d)(?=.*[^a-zA-Z\d].*[^a-zA-Z\d].*[^a-zA-Z\d])[-+%#a-zA-Z\d]+$
将你的特殊字符集添加到上面正则表达式中的最后一个 [...] 中(现在我只是放了一些-+%#)。
^                              - beginning of line/string
(?=.{8})                       - positive lookahead to ensure we have at least 8 chars
(?=.*[A-Z])                    - ...to ensure we have at least one uppercase char
(?=.*[a-z])                    - ...to ensure we have at least one lowercase char
(?=.*\d.*\d.*\d                - ...to ensure we have at least three digits
(?=.*[^a-zA-Z\d].*[^a-zA-Z\d].*[^a-zA-Z\d]) 
                               - ...to ensure we have at least three special chars
                                    (characters other than letters and numbers)
[-+%#a-zA-Z\d]+                - combination of allowed characters
$                              - end of line/string

Omega,感谢您的回复,但我发现您的正则表达式形式令我困惑,因为我是个新手。您能否请逐步详细解释一下这段代码? - MrPizzaFace
@FabioAnselmo - 我已经更新了我的答案,并添加了这样的信息。 - Ωmega
@rekire - (?= ... ) 是一个正向先行断言(请参见更新的答案)。 - Ωmega
(?=.[^a-zA-Z\d].[^a-zA-Z\d])如何确保特殊字符?RegEx参考显示\W为特殊字符。感谢解释。另外,如果我想要@#$这样的字符,会是这个样子:[ / @ / # / $ a-zA-Z\d]+ - MrPizzaFace
@FabioAnselmo - (?=.*[^a-zA-Z\d].*[^a-zA-Z\d].*[^a-zA-Z\d]) 是一个正向前瞻条件,必须满足才能找到匹配项。这个条件是:一些或没有字符 .*,后跟特殊字符 [^a-zA-Z\d],后跟一些或没有字符,再后跟特殊字符。特殊字符被定义为 [^a-zA-Z\d],即除字母或数字以外的任何字符。在正则表达式的末尾,你可以设置允许的字符集合 [-+%#a-zA-Z\d],其中 + 表示一个或多个。在 [...] 集合中没有字符分隔符。将 - 列为第一个,不要将 ^ 列为第一个。 - Ωmega
显示剩余4条评论

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

test$ABC5#8 不是有效的,因为您要求超过2个数字和特殊符号

A-Z
a-z
0-9 > 2
special chars > 2
string length >= 8

嘿,对于混淆感到抱歉。请注意代码。它是无效的,因为字符不相邻。它将在我使用例如:test$$ABC44 进行验证。我会更正这个例子。抱歉。 - MrPizzaFace
将数字和特殊符号中的“{3,}”改为“{2,}”,就可以通过。 - burning_LEGION

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接