【问题标题】:Regex (regular expression) for password validationRegex(正则表达式)用于密码验证
【发布时间】:2014-10-14 05:31:25
【问题描述】:

什么是正确的regex,以满足以下密码标准:

  • 必须包含至少 1 个小写字母。
  • 必须至少包含 1 个大写字母。
  • 必须至少包含 1 个数字。
  • 必须至少包含 1 个特殊字符(仅允许使用以下特殊字符:!#%)。
  • 不得包含除A-Za-z0-9!#% 之外的任何其他字符(例如,不得包含;)。
  • 长度必须为 8 到 32 个字符。

这是我尝试过的,但它不起作用:

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

但应该是:

^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[\!\#\@\$\%\&\/\(\)\=\?\*\-\+\-\_\.\:\;\,\]\[\{\}\^])[A-Za-z0-9!#%]{8,32}

但无论如何,Unihedron 的解决方案更好,只是想为将来会阅读此问题的用户提及这一点。 :)

Unihedron 的解决方案(也可以在下面的他的答案中找到,我自己复制了它,以防他在他的答案中更改(将其更新为更好的版本)):

^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=\D*\d)(?=.*?[!#%])[A-Za-z0-9!#%]{8,32}$

我最终得到了以下regex

^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=\D*\d)(?=.*?[\!\#\@\$\%\&\/\(\)\=\?\*\-\+\-\_\.\:\;\,\]\[\{\}\^])[A-Za-z0-9\!\#\@\$\%\&\/\(\)\=\?\*\-\+\-\_\.\:\;\,\]\[\{\}\^]{8,60}$

再次感谢 Unihedron 和 skamazin。赞赏!

【问题讨论】:

  • 也分享你的努力。
  • 如果它只有 32 个字符长...为什么不直接遍历字符串 5 次...在这种情况下仍然是 O(1)
  • 顺便说一句,您不必担心帖子更改,您可以随时view revisions of posts编辑。
  • 关于 PHP 的 IDK,但你可以做类似的事情。 ToLower() 然后与原始字符串比较, ToUpper() 和比较。将 (0-9) 替换为 '' 并比较等。由于长度很短,您根本不必担心运行时间。与正则表达式相比,IMO 提高了可读性。不知道它是否更快
  • @Steve 可读代码? Nonono, don't ever...

标签: regex passwords password-protection


【解决方案1】:

使用这个正则表达式:

/^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=\D*\d)(?=[^!#%]*[!#%])[A-Za-z0-9!#%]{8,32}$/

这是regex demo


了解更多:

【讨论】:

  • @Unihedron 明星* 做了什么?
  • @tastro 星星是zero to one 量词。在正则表达式中使用这些,它允许通过跳过不相关字符(无回溯)来进行有效匹配。另请参阅Stack Overflow Regex Reference
  • @Unihedron 你能帮我澄清一下吗:使用(?=[^a-z]*[a-z])(?=.*[a-z]) 更快(正则表达式引擎执行的步骤数),因为第二个会使引擎回溯直到匹配,正确的?第一个不需要回溯,因为[^a-z]* 会在第一个字母字符处停止,然后[a-z] 会匹配那个字母字符,对吗?
  • @skamazin 是的,这是正确的。这种技术可以通过正则表达式引擎的工作方式来解释——有两个指针,一个在模式上,另一个在你的字符串上。指针尽可能多地执行,因此最佳正则表达式是那些防止回溯(.*? 优于 .* 对于文字序列)或适当地“滚动”不必要的内容(参见 this 一个很好的例子) - ,?[^,]* 很神奇!)。
【解决方案2】:

this 上测试您可能的密码,看看它们是否给您正确的结果

我使用的正则表达式是:

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

【讨论】:

  • 抱歉,我将问题读作 1 个数字或 1 个特殊字符,所以我创建了一个非捕获交替组。我的错。
  • @skamazin 您的regex 的哪一部分确保不能有分号;(例如)作为特殊字符?只是想更好地理解regex。 :)
  • @tastro 最后一点:前四组断言字符存在的条件。 [A-Za-z0-9!#%]{8,32} 表示整个字符串由列表 A-Za-z0-9!#% 中的 8 到 32 个字符组成。
  • @tastro 整个匹配锚定^$,因此[...]{n,u} 将断言该列表完全支持字符串区域。 Lookaheads do not affect the match.
  • 正如 Unihedron 已经指出的那样,前瞻不会捕获,因此所有捕获都发生在正则表达式的末尾;特别是这个位:[A-Za-z0-9!#%]{8,32} 只有当字符串由大写/小写字母、数字和!#% 组成时才会生成。因为;不包括在内,所以不允许匹配正则表达式。如果要将; 添加到列表中,它将允许该字符。 [A-Za-z0-9!#%] 是一个白名单,这意味着这些是唯一允许的字符。
猜你喜欢
  • 2011-07-10
  • 1970-01-01
  • 2011-05-06
  • 2016-10-19
  • 2011-03-24
  • 1970-01-01
相关资源
最近更新 更多