【问题标题】:Java based Regex for Azure AD cloud user account password policyAzure AD 云用户帐户密码策略的基于 Java 的 Regex
【发布时间】:2018-08-30 16:05:46
【问题描述】:

我正在尝试使用正则表达式在 Java 中实现 Azure AD cloud user account policy

我已经定义了一个模式字符串,我使用string.matches(pattern)如下:

// ONE OF THESE CHARACTER CLASS COMBINATIONS NEED TO BE MET
// combination of lowercase, uppercase and numbers, 8 to 16 characters in length
// combination of lowercase, uppercase and symbols, 8 to 16 characters in length
// combination of lowercase, numbers and symbols, 8 to 16 characters in length
// combination of uppercase, numbers and symbols 8 to 16 characters in length
private static final String PATTERN_PASSWORD_REGEX = new StringBuilder('^')
        .append("((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])).{8,16}")
        .append('|') // -or-
        .append("((?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&*\\-_!+=\\[\\]{}|\\:‘,.?\\/`~“\\(\\);])).{8,16}")
        .append('|') // -or-
        .append("((?=.*[a-z])(?=.*[0-9])(?=.*[@#$%^&*\\-_!+=\\[\\]{}|\\:‘,.?\\/`~“\\(\\);])).{8,16}")
        .append('|') // -or-
        .append("((?=.*[A-Z])(?=.*[0-9])(?=.*[@#$%^&*\\-_!+=\\[\\]{}|\\:‘,.?\\/`~“\\(\\);])).{8,16}")
        .append('$')
        .toString();

public static boolean validate(String password) {
    return password.matches(PATTERN_PASSWORD_REGEX);
}

不知何故,它将空格视为特殊字符,即使我 not 将其包含在正则表达式中。下面的 JUnit 测试方法将传递除最后一个之外的所有断言。

@Test
public void testPassword() {

    Assert.assertTrue("password is valid", validate("Abcdef12"));
    Assert.assertTrue("password is valid", validate("abcde$12"));
    Assert.assertTrue("password is valid", validate("ABCDE%12"));
    Assert.assertTrue("password is valid", validate("Abcde~12"));
    Assert.assertFalse("password is invalid", validate("abcdefgh"));
    Assert.assertFalse("password is invalid", validate("12345678"));
    Assert.assertFalse("password is invalid", validate("ABCDEFGH"));
    Assert.assertFalse("password is invalid", validate("ABCDefgh"));
    Assert.assertFalse("password is invalid", validate("!~$:-_@&"));

    // This assertion fails...
    Assert.assertFalse("password is invalid", validate("Abcdef 12"));
}

我已经看到关于 SO 正则表达式问题的非常优雅的答案,但通常它们不涉及字符类组合。希望有人能告诉我我做错了什么,或者是否有更好的方法。

【问题讨论】:

  • Abcdef 12((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])).{8,16} 部分匹配,因此它是 false,因为 validate 返回 true。
  • 我现在看到了问题,我的正则表达式没有排除组件,阻止了不允许的字符类。它使用的是包容性模式。是否有更好/优雅的方式来实现要求?
  • 我会在我的孩子上床睡觉时检查它,如果我没有早点入睡 :) 几个小时或一个半小时。
  • 是否值得尝试先使用独占检查,然后再使用包含检查?换句话说,也许检查字符串是否包含不在集合a-zA-Z0-9@#$%^&*-_!+=[]{}|\:‘,.?/`~“(); 中的字符,并抢占实际的、包含性的检查是否存在所需的字符组合。
  • 啊哈,所以这些不仅是必需的字符,也是允许的字符。只需将它们全部放入 char 类而不是 .。见regex101.com/r/LhulES/3。将.{8,16} 替换为[-A-Za-z0-9@#$%^&*_!+=\\[\\]{}|:',.?/`~\"();]{8,16}

标签: java regex azure azure-active-directory


【解决方案1】:

您需要在最后一部分指定您允许的字符,而不是点。将.{8,16} 替换为[-A-Za-z0-9@#$%^&*_!+=\[\]{}|:',.?/`~\"();]{8,16}

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

请参阅regex demo

private static final String PATTERN_PASSWORD_REGEX = new StringBuilder('^(?:')
    .append("(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])")
    .append('|') // -or-
    .append("(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=.*[-@#$%^&*_!+=\\[\\]{}|:‘,.?/`~“();])")
    .append('|') // -or-
    .append("(?=[^a-z]*[a-z])(?=[^0-9]*[0-9])(?=.*[-@#$%^&*_!+=\\[\\]{}|:‘,.?/`~“();])")
    .append('|') // -or-
    .append("(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9])(?=.*[-@#$%^&*_!+=\\[\\]{}|:‘,.?/`~“();])")
    .append(')[-A-Za-z0-9@#$%^&*_!+=\\[\\]{}|:‘,.?/`~“();]{8,16}$')
    .toString();

【讨论】:

  • 感谢@Wiktor...除了提供实时正则表达式演示示例之外,更感谢您努力更新 Java 方法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
  • 2018-01-23
  • 2019-01-29
  • 1970-01-01
  • 2019-07-27
  • 2020-11-24
相关资源
最近更新 更多