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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2637896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 07:10:36  来源:igfitidea点击:

PHP regular expression for strong password validation

phpregexvalidationpasswords

提问by Jason

I've seen the following regular expression around the web.

我在网上看到了以下正则表达式。

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$

It validates only if the string:

它仅在字符串时验证:

   * contain at least (1) upper case letter
   * contain at least (1) lower case letter
   * contain at least (1) number or special character
   * contain at least (8) characters in length

I'd like to know how to convert this regular expression so that it checks the string to

我想知道如何转换这个正则表达式,以便它检查字符串

* contain at least (2) upper case letter
* contain at least (2) lower case letter
* contain at least (2) digits
* contain at least (2) special character
* contain at least (8) characters in length

Well, if it contains at least 2 upper,lower,digits and special characters then I wouldn't need the 8 characters length.

好吧,如果它至少包含 2 个大写、小写、数字和特殊字符,那么我不需要 8 个字符的长度。

Special characters include:

特殊字符包括:

`~!@#$%^&*()_-+=[]\|{};:'".,/<>?

`~!@#$%^&*()_-+=[]\|{};:'".,/<>?

回答by dawg

I have to agree with Alan. If the existing regex is so complicated, why try and do it in just one regex?

我必须同意艾伦的看法。如果现有的正则表达式如此复杂,为什么要尝试只用一个正则表达式来完成呢?

Just break it down into approachable simple steps. You have already done that.

只需将其分解为平易近人的简单步骤即可。你已经这样做了。

Now write 4 regex to validate your parts, add basic logic to the 4 regex and measure the length of the string. Done.

现在编写 4 个正则表达式来验证您的部分,将基本逻辑添加到 4 个正则表达式并测量字符串的长度。完毕。

Which would you rather debug, this:

你更愿意调试哪个,这个:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$(which does not work btw...)

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$(顺便说一句,这不起作用......)

or this:

或这个:

function valid_pass($candidate) {
   $r1='/[A-Z]/';  //Uppercase
   $r2='/[a-z]/';  //lowercase
   $r3='/[!@#$%^&*()\-_=+{};:,<.>]/';  // whatever you mean by 'special char'
   $r4='/[0-9]/';  //numbers

   if(preg_match_all($r1,$candidate, $o)<2) return FALSE;

   if(preg_match_all($r2,$candidate, $o)<2) return FALSE;

   if(preg_match_all($r3,$candidate, $o)<2) return FALSE;

   if(preg_match_all($r4,$candidate, $o)<2) return FALSE;

   if(strlen($candidate)<8) return FALSE;

   return TRUE;
}

Why folks feel they have to write a regex that no one can understand just so they can do it in one go is beyond me...

为什么人们觉得他们必须编写一个没人能理解的正则表达式,以便他们可以一次性完成,这超出了我的理解......



Ok ok -- if you really want a single regex, learn about lookaheadsto validate your rules.

好吧——如果你真的想要一个正则表达式,学习前瞻来验证你的规则。

This monster does what you asked in one go:

这个怪物一次性完成了你的要求:

^                                        # start of line
(?=(?:.*[A-Z]){2,})                      # 2 upper case letters
(?=(?:.*[a-z]){2,})                      # 2 lower case letters
(?=(?:.*\d){2,})                         # 2 digits
(?=(?:.*[!@#$%^&*()\-_=+{};:,<.>]){2,})  # 2 special characters
(.{8,})                                  # length 8 or more
$                                        # EOL 

Demo

演示

回答by Alan Moore

The best way to adapt that regex is to chuck it out and write some code instead. The required regex would be so long and complicated, you wouldn't be able to read it two hours after you wrote it. The equivalent PHP code will be tedious, but at least you'll be able understand what you wrote.

适应该正则表达式的最佳方法是将其丢弃并编写一些代码。所需的正则表达式会如此冗长和复杂,您将无法在编写后两小时阅读。等效的 PHP 代码会很乏味,但至少您将能够理解您所写的内容。

This isn't meant as a slam on you, by the way. Regexes are just barely suitable for password-strength validation in most cases, but your requirements are more complicated than usual, and it's just not worth it. Also, that regex you posted is crap. Never trust regexes you find floating around the web. Or any code, for that matter. Or, heck, anything. :-/

顺便说一下,这并不是要抨击你。在大多数情况下,正则表达式几乎不适合密码强度验证,但您的要求比平时更复杂,而且不值得。另外,您发布的正则表达式是垃圾。永远不要相信你在网上发现的正则表达式。或者任何代码,就此而言。或者,见鬼,任何东西。:-/

回答by Gumbo

If you really want to use a regular expression, try this:

如果你真的想使用正则表达式,试试这个:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$

Some explanation:

一些解释:

  • (?=^(?:[^A-Z]*[A-Z]){2})tests for two repetitions of [^A-Z]*[A-Z]which is a sequence of zero or more characters except uppercase letters followed by one uppercase letter
  • (?=^(?:[^a-z]*[a-z]){2})(same as above with lowercase letters)
  • (?=^(?:\D*\d){2})(same as above with digits)
  • (?=^(?:\w*\W){2})(same as above with non-word characters, but you may change \Wwith a character class of whatever special characters you want)
  • ^[A-Za-z\d\W]{8,}$tests the length of the whole string consisting only of character of the union of all other character classes.
  • (?=^(?:[^A-Z]*[A-Z]){2})测试两次重复[^A-Z]*[A-Z]是零个或多个字符的序列,除了大写字母后跟一个大写字母
  • (?=^(?:[^a-z]*[a-z]){2})(同上,小写字母)
  • (?=^(?:\D*\d){2})(同上,有数字)
  • (?=^(?:\w*\W){2})(与上面的非单词字符相同,但您可以\W使用您想要的任何特殊字符的字符类进行更改)
  • ^[A-Za-z\d\W]{8,}$测试仅由所有其他字符类的联合的字符组成的整个字符串的长度。