【问题标题】:Regex for checking > 1 upper, lower, digit, and special char用于检查 > 1 个大写、小写、数字和特殊字符的正则表达式
【发布时间】:2011-01-22 08:57:43
【问题描述】:

^.(?=.{15,})(?=.\d)(?=.[az])(?=.[AZ] )(?=.[!@#$%^&+=]).*$

这是我目前使用的正则表达式,它将评估每个中的 1 个:上、下、数字和我选择的特殊值。我的问题是如何让它检查其中的每一个?我还问,因为似乎很难为此编写测试用例,因为我不知道它是否只是评估它需要的第一组标准。这是一个密码,但是要求它必须是基于我们正在使用的包的正则表达式形式。

编辑

好吧,我急于验证我忘记验证我的字符串长度的表达式。感谢 Ken 和 Gumbo 帮助我解决这个问题。

这是我正在执行的代码:

我很抱歉,因为正则表达式不是我的领域。

我使用的密码是以下字符串“$$QiouWER1245”,我现在遇到的行为是随机选择通过或失败。对此有什么想法吗?

Pattern pattern = Pattern.compile(regEx);
Matcher match = pattern.matcher(password);  
while(match.find()){
    System.out.println(match.group()); 
}

从我看到的结果来看,如果它评估为 true,它将把密码中的值扔回给我,否则它是一个空字符串。

【问题讨论】:

    标签: java regex


    【解决方案1】:

    就个人而言,我认为强制使用所有三个字符类的密码策略不是很有帮助。通过让人们输入更长的密码,您可以获得相同程度的随机性。如果用户必须遵守太多密码规则(这使得密码难以记住),他们往往会感到沮丧并写下密码。我建议计算熵位并确保它们大于 60(通常需要 10-14 个字符的密码)。每个字符的熵大致取决于字符数、它们使用的字符集范围以及它们在字符集之间切换的频率(我猜像 HEYthere 这样的密码比 heYThEre 更容易预测)。

    另一个注意事项:您是否打算不计算键盘右侧的符号(句点、逗号、尖括号等)?

    如果您仍然需要找到两个字符的组,为什么不重复每个模式呢?例如,将 (?=.\d) 转换为 (?=.\d.*\d)。

    对于您的测试用例,如果您担心它只会检查第一个条件,请编写一个测试用例,确保以下每个密码都失败(因为每种情况下只有一个条件不满足):只是为了好玩,我颠倒了每个字符集的期望顺序,尽管除非有人在将来的某个日期删除/忘记了 ?=,否则它可能不会有什么不同。

    !@#TESTwithoutnumbers
    TESTwithoutsymbols123
    &*(testwithoutuppercase456
    +_^TESTWITHOUTLOWERCASE3498
    

    我应该指出,从技术上讲,这些密码都不应该是可接受的,因为它们使用字典单词,每个字符大约有 2 位熵,而不是更像 6 位。但是,我意识到很难编写一个(可维护的并且高效)正则表达式来检查字典中的单词。

    【讨论】:

    • 作为一名软件测试人员,我必须将需求回馈给某人,并解释为什么它们不足或错误。您是否有能力提出替代解决方案或替代要求?
    • 不,我没有这种能力,我也不认为团队中的任何人在不久的将来会有这种能力,原因有很多。
    【解决方案2】:

    试试这个:

    "^(?=(?:\\D*\\d){2})(?=(?:[^a-z]*[a-z]){2})(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^!@#$%^&*+=]*[!@#$%^&*+=]){2}).{15,}$"
    

    这里使用非捕获组(?:…) 对条件进行分组并重复它们。我还使用每个字符类的补码进行优化,而不是通用的.

    【讨论】:

    • 感谢 Gumbo,但是基于我拥有的少量评估代码,这确实失败了。可能是我的评价有误。
    • 我看到您编辑了您的帖子 Gumbo,因此我尝试了最新的更改。就目前而言,字符串正在寻找 4 而不是 2 大写、小写、数字和特价
    • @Woot4Moo:我刚刚添加了引号。 ;-)
    • @Gumbo,很好地展示了正则表达式技巧:)
    • 旁注:我不知道是否有人再支持 IE5.5,但是如果在 javascript 中使用这将触发正则表达式前瞻错误。更多细节在这里:blog.stevenlevithan.com/archives/regex-lookahead-bug
    【解决方案3】:

    我不确定一个大的正则表达式是否是正确的方法。它已经看起来太复杂了,将来很难改变。

    我的建议是按以下方式构造代码:

    • 检查字符串是否有 2 个小写字符
      • 如果找不到则返回失败或继续
    • 检查字符串是否有 2 个大写字符
      • 如果找不到则返回失败或继续

    这也将允许您传递返回码或错误字符串,说明密码不被接受的原因,并且代码会更简单。

    【讨论】:

    • 那将是理想的,但是我必须根据我们正在使用的包使用正则表达式。
    • 您使用的是什么包,为什么需要使用它?
    • 我正在编写对复杂字符串使用正则表达式验证的安装程序。安装构建器
    • 它是 BitRock InstallBuilder 吗?如果是这样,那么您是否可以不只指定多个验证规则,例如。 /[A-Z].*[A-Z]/、/[a-z].*[a-z]/ 和 /[0-9].*[0-9]/ 等等等等。
    • 他们有一个正则表达式验证器,不过感谢您的意见。
    【解决方案4】:

    如果我正确理解您的问题,您需要至少 15 个字符,并且至少需要 2 个大写字符、至少 2 个小写字符、至少 2 个数字和至少 2 个特殊字符。在这种情况下,你可以这样:

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

    顺便说一句,您原来的正则表达式在 \d 之前有一个额外的反斜杠

    【讨论】:

    • 这个要求是正确的,额外的反斜杠是为了在我的 Java 领域的测试字符串中转义它。
    • @Woot4Moo:第二个反斜杠不是来自像"…\\d…"这样的字符串声明吗?
    • @Ken 我编辑了我的帖子以显示我使用的密码,你有没有机会帮我写一个测试用例来证明它有效?它是否有效似乎是相当随机的。
    • 我只是使用一个简单的 perl 脚本来测试正则表达式。上面的密码不匹配,因为它只有 13 个字符,并且正则表达式的第一部分 (?=.{15,}) 设置的最小长度为 15 个字符。
    • @Ken 哦,我亲爱的 jeebus,我不敢相信我只是对自己这样做。
    猜你喜欢
    • 2016-02-13
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多