【问题标题】:Regular expression to enforce complex passwords, matching 3 out of 4 rules正则表达式强制执行复杂密码,匹配 4 条规则中的 3 条
【发布时间】:2011-03-28 20:49:03
【问题描述】:

我有以下标准来为符合以下规则的密码创建正则表达式:

  1. 密码长度必须为 8 个字符(我可以这样做:-))。

密码必须包含来自以下 4 条规则中的至少 3 条的字符:

  1. 大写
  2. 小写
  3. 数字
  4. 非字母数字

我可以使用以下表达式使表达式匹配所有这些规则:

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

但我正在努力解决如何以只需要解决 4 条规则中的任何 3 条的方式做到这一点。

谁能帮我解决这个问题?

【问题讨论】:

  • 我不得不说这是其中一种情况,我认为如果你有 4 个不同的正则表达式,你的代码可能会更具可读性。然后可能有一个计数,并且对于每个匹配的正则表达式,您都会增加计数,然后最后您只需检查计数是否为 3 或更高。
  • 您使用哪种编程语言?

标签: regex


【解决方案1】:

不要使用一个正则表达式来检查它。

if (password.length < 8)
  alert("bad password");
var hasUpperCase = /[A-Z]/.test(password);
var hasLowerCase = /[a-z]/.test(password);
var hasNumbers = /\d/.test(password);
var hasNonalphas = /\W/.test(password);
if (hasUpperCase + hasLowerCase + hasNumbers + hasNonalphas < 3)
  alert("bad password");

如果您必须使用单个正则表达式:

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

此正则表达式未针对效率进行优化。它由A·B·C + A·B·D + A·C·D + B·C·D 构造,并进行了一些分解。细分:

^
(?:
    (?=.*[a-z])       # 1. there is a lower-case letter ahead,
    (?:               #    and
        (?=.*[A-Z])   #     1.a.i) there is also an upper-case letter, and
        (?=.*[\d\W])  #     1.a.ii) a number (\d) or symbol (\W),
    |                 #    or
        (?=.*\W)      #     1.b.i) there is a symbol, and
        (?=.*\d)      #     1.b.ii) a number ahead
    )
|                     # OR
    (?=.*\W)          # 2.a) there is a symbol, and
    (?=.*[A-Z])       # 2.b) an upper-case letter, and
    (?=.*\d)          # 2.c) a number ahead.
)
.{8,}                 # the password must be at least 8 characters long.
$

【讨论】:

    【解决方案2】:

    您可以使用以下正则表达式:

    (^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$)?(^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).*$)?(^(?=.*\d)(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)?(^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)?
    

    密码最小长度为 8,最大长度为 32,您可以使用以下正则表达式:

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

    【讨论】:

    • 四次中你需要一次取 3 次,如果其中任何一个匹配密码模式将被验证。
    • 为什么要设置最大密码长度?
    • 是否有理由拥有最大密码长度?这篇文章 (source) 没有最大长度,它有效且强大吗? var strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&amp;\*])(?=.{8,})");。它强制:至少 1 个小写,至少 1 个大写,至少 1 个数字,至少 1 个特殊字符,至少 8 个字符长度。有趣的是,即使有这些规则,howsecureismypassword 表示需要 9 个小时才能破解 aX1@a610
    • 刚刚注意到 ^ (strongRegex.test(string);) 如果字符串中有空格,则返回 true,不确定这是否有问题。
    【解决方案3】:

    我建议单独进行检查,然后将匹配的总数加起来。

    (我也不会在其中任何一个中使用正则表达式,但这只是我个人的 POV - 即它们妨碍了可读性并且通常是一次性代码)

    【讨论】:

      【解决方案4】:

      可以编写一个非常复杂的正则表达式来做到这一点。相反,我建议编写四个不同的正则表达式,每个规则一个,并逐个测试它们,计算其中有多少匹配。如果四分之三做到了,请接受密码。

      【讨论】:

      • 与其他解决方案相比,它的巨大优势在于,您实际上可以阅读、推理并在五年后维护它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      相关资源
      最近更新 更多