有没有办法合并这两个正则表达式?

时间:2016-05-04 12:23:34

标签: javascript java regex passwords

我需要使用以下规则检查密码字符串:

  • 只允许使用小写字母,大写字母,数字和一些特殊字符(见下文)。
  • 最少8个字符,最多16个字符。
  • 密码必须包含以下四个组中的三个中的至少一个字符:

    • 小写字母
    • 大写字母
    • 数字字符
    • 特殊字符(!@#$%& / =?_。,:; - )

为了实现这个目标,我做了两次验证。简单的是第一步,检查允许的字符和长度:

^[a-zA-Z0-9!@\#$%&/=?_.,:;\-]{8,16}$

第二个有点复杂,但我可以通过Stackoverflow answer来解决它:

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

我认为这可能是一个明确而简单的2步骤解决方案......但是...... 有没有办法合并两个正则表达式?

我想在Java,JavaScript和Lua上应用该解决方案。

2 个答案:

答案 0 :(得分:1)

首先我要强调一点,我不喜欢你的密码政策。为什么禁止使用其他符号或超过16个字符的密码?如果可能的话,请不要包含这些规则。

为了清楚起见,我已经用扩展形式写了这个正则表达式(即忽略了空格):

/\A 
  (?=.{8,16}\z)                     # Must contain 8-16 characters
  (?!.*[^a-zA-Z\d!@#$%&\/=?_.,:;-]) # Must not contain other characters
  (?=.*\d)                          # Must contain a digit
  (?=.*[a-z])                       # Must contain a lower case character
  (?=.*[A-Z])                       # Must contain an upper case character
  (?=.*[!@#$%&\/=?_.,:;-])          # Must contain a symbol from this list
/x

上述模式解决了强制执行所有四个规则的问题。理论上,你可以将最后4个条件包装成4个"或者#34;小组 - 就像你原来的例子一样。

然而,再次,我不推荐它。如果您在函数内执行一系列单独的检查,那么您的代码将更易读,有用且可维护。 (例如,这意味着您可以显示更多有用的错误消息,而不仅仅是"正则表达式失败!"。

但是既然你问过....这是正则表达式的怪物:

/\A 
  (?=.{8,16}\z)
  (?!.*[^a-zA-Z\d!@#$%&\/=?_.,:;-])
  (
    (?=.*\d)
    (?=.*[a-z])
    (?=.*[A-Z])
  |
    (?=.*\d)
    (?=.*[a-z])
    (?=.*[!@#$%&\/=?_.,:;-])
  |
    (?=.*\d)
    (?=.*[A-Z])
    (?=.*[!@#$%&\/=?_.,:;-])
  |
    (?=.*[a-z])
    (?=.*[A-Z])
    (?=.*[!@#$%&\/=?_.,:;-])
  )
/x

如果您不想/无法访问/x修饰符,请删除所有空格。

答案 1 :(得分:0)

整个验证的单个正则表达式的缺点是,正则表达式很难阅读和维护。将正则表达式条件分离为每个条件的单个检查,并且简单检查String的长度将是更合适且更易读的解决方案。在我看来,以下代码对密码的验证与单个正则表达式一样好,但最好是维护和阅读。

public static void main(String[] args) {
    System.out.println(isPasswordValid("Ab$123456"));
    System.out.println(isPasswordValid("b$11234566"));
    System.out.println(isPasswordValid("Ab$1234634634534252"));
    System.out.println(isPasswordValid("$112512312512"));
    System.out.println(isPasswordValid("A$115 223"));
}   

private static boolean isPasswordValid(String password) {
    // The password is to short or to long
    if(password.length() < 8 || password.length() > 16) {
        return false;
    }
    int matchedConditions = 0;
    // Check for invalid characters
    if(password.matches(".*[^A-Za-z0-9!@#$%&/=?_.,:;-].*")) {
        return false;
    }
    // is an uppercase letter present, increase matched condition
    if(password.matches(".*[A-Z].*")){
        ++matchedConditions;
    }
    // is a lowercase letter present, increase matched condition
    if(password.matches(".*[a-z].*")){
        ++matchedConditions;
    }
    // is a numeric value present, increase matched condition
    if(password.matches(".*[0-9].*")){
        ++matchedConditions;
    }
    // is a special character present, increase matched condition
    if(password.matches(".*[!@#$%&/=?_.,:;-].*")){
        ++matchedConditions;
    }
    // Return if at least 3 conditions were met
    return matchedConditions >= 3;
}

输出:

true
true
false
false
false