密码复杂度正则表达式帮助

4

我正在使用以下正则表达式来验证密码复杂度:

/^.*(?=.{6,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/

简而言之:2个小写字母,2个大写字母,2个数字,最小长度为6,最大长度为12。

它完美地工作,除了在我同时使用最小长度时的最大长度。

例如:

/^.*(?=.{6,})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/

这个正确地要求最小长度为6!

以及这个:

/^.*(?=.{,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/

正确的要求最大长度为12。

但是,当我像第一个例子一样将它们配对在一起时,它就无法正常工作!

发生了什么?谢谢!


2
你有什么特别的原因要阻止别人使用13个或更多字符(从而更安全)的密码吗? - nickf
有些系统实际上有它们可以接受的最大密码长度,我记得在我以前的联合Unix/Windows网络上,我们不能超过8个字符。 - hhafez
除非存在不可避免的技术限制(例如在@hhafez的情况下)对密码长度施加硬性限制,否则最佳实践绝对是不必要地限制密码长度(如@nickf所说)。反正你也不需要存储密码,只需存储其哈希值,而无论密码是2个字符还是200个字符,哈希值通常都是相同的长度。 - Frank Farmer
谢谢大家的回复,这种情况下没有特别的原因限制最大长度,仅仅是为了完整而已! :) - Alex Weber
1个回答

13

你想要:

/^(?=.{6,12}$)...
你正在做的是查找:任意一个字符序列后面跟着:
  • 6-12个字符
  • 另一个字符序列后面再跟着2个数字
  • 另一个字符序列后面再跟着2个大写字母
  • 另一个字符序列后面再跟着2个小写字母

而且这些都在另一个字符序列后面。这就是为什么最大长度不起作用,因为30个字符后面跟着00AAaa还有另外30个字符也会匹配成功。

此外,你现在是强制要求两个数字连在一起。如果想要稍微宽松一点,但仍要求字符串中至少有两个数字:

/^(?=.{6,12}$)(?=(.*?\d){2})(?=(.*?[A-Z]){2})(?=(.*?[a-z]){2})/

最后请注意我使用的是非贪婪表达式(.*?)。这将避免很多回溯,在这种验证情况下通常应该使用它。与之相比的是:

(.*\d){2}

并且

(.*?\d){2}

第一个正则表达式会使用 .* 匹配所有字符,然后查找一个数字。它不会找到任何一个数字,因为数字在字符串的末尾,所以它会回溯一个字符并继续查找数字。如果它没有找到数字,它将一直回溯直到找到为止。在找到数字后,它将再次匹配整个表达式,这将触发更多回溯。

这就是所谓的贪婪通配符的意思。

第二个版本将0个字符传递给.*?,然后查找数字。如果它不是数字,.*? 将继续抓取另一个字符并查找数字,以此类推。特别是在长搜索字符串中,这可以提高几个数量级的速度。对于短密码来说,几乎不会有什么差异,但了解正则表达式匹配器的工作原理并编写最佳的正则表达式是一个好习惯。

话虽如此,这可能是自作聪明的例子。如果密码因不满足这些条件而被拒绝,那么如何确定哪个条件失败以便向用户提供有关该修复什么的反馈?在实践中,编写程序解决问题可能更可取。


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