【问题标题】:Password validation is not allowing special character at the end of the screen密码验证不允许屏幕末尾的特殊字符
【发布时间】:2016-01-22 08:29:19
【问题描述】:

我写了一个正则表达式来根据以下条件验证密码。

您的密码长度应为 8 到 20,并且必须包含至少 2 个字母、1 个数字和 1 个特殊字符。空间不允许

我的正则表达式是-

final String PASSWORD_PATTERN = 
   "^(?=.*[0-9].{1})(?=.*[A-Za-z].{2})(?=.*[@#$%^&+=].{1})(?=\\S+$).{8,}$";

它在所有其他情况下都有效,除非我在字符串末尾输入任何特殊字符。请有人建议我做错了什么?

【问题讨论】:

  • 匹配时是否使用了trim()(用于字符串)?
  • 是的,即使它不接受。
  • 图案不符合您的要求。
  • 问题是你的PASSWORD_PATTERN
  • 是的,这就是问题所在,但是我需要解决这个问题。我在哪里做错了?

标签: java android regex


【解决方案1】:

如果不喜欢使用正则表达式,可以编写一个函数来遍历字符串并计算数字、字母或特殊字符的数量。

boolean isValidPassword(char[] pass) {
    int letters = 0, digits = 0, specialChars = 0;
    if (pass.length < 8 || pass.length > 20) {
        return false;
    }
    for (int i = 0; i < pass.length; i++) {
        char ch = pass[i];
        if (Character.isLetter(ch)) {
            letters++;
        }
        else if (Character.isDigit(ch)) {
            digits++;
        }
        else if (isSpecialChar(ch)) {
            specialChars++;
        }
        else if (Character.isWhiteSpace(ch)) {
            return false;
        }
    }
    return !(letters < 2 || digits < 1 || specialChars < 1);
}

static boolean isSpecialChar(char c) {
    switch (c) {
        case '@':
        case '#':
        case '$':
        case '%':
        case '^':
        case '&':
        case '+':
        case '=':
            return true;
        default:
            return false;
    }
}

请注意,这也解决了使用Strings 时的安全问题,如this articlethis question 所述。

【讨论】:

    【解决方案2】:

    该模式不符合您的规范,因为量词 {1}{2} 应用于 .而不是正确的模式。此外,最后一个量词 {8,} 允许从 8 到任意数量的字符,但您需要将它们的数量限制为 20。另外,请注意 {1} 是完全多余的。此外,我建议在前瞻中使用principle of contrast(检查Lookahead Example: Simple Password Validation)。

    你可以使用

    final String PASSWORD_PATTERN = 
      "^(?=[^0-9]*[0-9])(?=(?:[^A-Za-z]*[A-Za-z]){2})(?=[^@#$%^&+=]*[@#$%^&+=])\\S{8,20}$";
    

    regex demo

    解释

    • ^ - 字符串开始
    • (?=[^0-9]*[0-9]) - 必须至少有一位数字(在可选的非数字之后)
    • (?=(?:[^A-Za-z]*[A-Za-z]){2}) - 应该有 2 个 ASCII 字母(使用 \pL 匹配 Unicode 字母及其对应类 \PL 匹配非 Unicode 字母的字符)
    • (?=[^@#$%^&amp;+=]*[@#$%^&amp;+=]) - 集合中必须至少有 1 个特殊符号
    • \\S{8,20} - 8 到 20 个非空白符号
    • $ - 字符串结束

    如果任何前瞻返回false,则整个匹配失败。它们都只执行一次,就在字符串开始之后,第一个符号之前。

    【讨论】:

    • 很好,你使这个正则表达式简单
    • 是的,它工作正常。但是,如果我输入任何特殊字符,例如 (!, -, ", ;..),将不起作用。所以,我们在正则表达式中是否有任何集合(例如对于特殊字符,对于数字,它的 d 类似)包含所有这些特殊字符?
    • 使用^(?=[^0-9]*[0-9])(?=(?:[^A-Za-z]*[A-Za-z]){2})(?=[^\\pP\\pS]*[\\pP\\pS])\\S{8,20}$\pP 匹配标点符号,\pS 匹配符号。
    • java.util.regex.PatternSyntaxException:索引 54 附近的 Unicode 属性不正确:01-22 14:56:48.483 30115-30115/com.visualoan E/AndroidRuntime:^(?=[^0- 9]*[0-9])(?=(?:[^A-Za-z]*[A-Za-z]){2})(?=[^\pP\pS]*[\pP \pS])\S{8,20}$‌​
    • 它是 Android,它使用的正则表达式与 Java 略有不同。尝试使用\\p{P}\\p{IsP} 而不是\\pP\\pS 类似)。
    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 2014-07-25
    • 2021-09-28
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 2020-01-23
    相关资源
    最近更新 更多