用于密码验证的Regex Java

时间:2010-09-27 08:34:36

标签: java regex

我正在为密码验证创建一个regexp,以便在Java应用程序中用作配置参数。

正则表达式是:

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

密码政策是:

  • 至少8个字符

  • 至少包含一位数字

  • 包含至少一个较低的alpha char和一个较高的alpha char

  • 在一组特殊字符(@#%$^等)中包含至少一个字符。

  • 不包含空格,标签等

我只缺少第5点。我无法检查空格,制表符,回车等等的正则表达式。

有人可以帮助我吗?

17 个答案:

答案 0 :(得分:267)

试试这个:

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

说明:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

添加,修改或删除单个规则很容易,因为每个规则都是一个独立的“模块”。

(?=.*[xyz])构造会占用整个字符串(.*)并回溯到[xyz]可以匹配的第一个匹配项。如果找到[xyz]则成功,否则失败。

替代方案是使用不情愿的限定符:(?=.*?[xyz])。对于密码检查,这几乎没有任何区别,对于更长的字符串,它可能是更有效的变体。

当然,最有效的变体(但最难阅读和维护,因此最容易出错)将是(?=[^xyz]*[xyz])。对于这个长度的正则表达式并且为了这个目的,我不建议这样做,因为它没有真正的好处。

答案 1 :(得分:46)

使用正则表达式的简单示例

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "aaZZa44@"; 
      String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
      System.out.println(passwd.matches(pattern));
   }
}

说明:

  • (?=.*[0-9])数字必须至少出现一次
  • (?=.*[a-z])小写字母必须至少出现一次
  • (?=.*[A-Z])大写字母必须至少出现一次
  • (?=.*[@#$%^&+=])特殊字符必须至少出现一次
  • (?=\\S+$)整个字符串中不允许有空格
  • .{8,}至少8个字符

答案 2 :(得分:10)

以前给出的所有答案都使用相同(正确)的技术为每个要求使用单独的前瞻。但它们包含一些低效率和潜在的大量错误,具体取决于实际使用密码的后端。

我将从接受的答案开始使用正则表达式:

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

首先,由于Java支持\A\z,我更喜欢使用它们来确保整个字符串经过验证,与Pattern.MULTILINE无关。这不会影响性能,但可以避免在重复使用正则表达式时出错。

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

通过将变量量词{8,}置于限制允许的速记\S上,检查密码不包含空格并检查其最小长度可以一次性使用全部完成字符:

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

如果提供的密码确实包含空格,则所有检查都将完成,只是在空格上进行最终检查失败。用\S替换所有点可以避免这种情况:

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

只有在您真的想要允许任何角色时才应使用该点。否则,使用(否定的)字符类将正则表达式限制为仅允许真正允许的字符。虽然在这种情况下没有什么区别,not using the dot when something else is more appropriate是一个非常好的习惯。我看到catastrophic backtracking的案例太多了,因为开发人员懒得使用比点更合适的东西。

由于初始测试很有可能在密码的前半部分找到合适的字符,因此惰性量词可能更有效:

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

但是现在对于一个非常重要的问题:没有一个答案提到原始问题似乎是由一个用ASCII思考的人写的。但在Java中,字符串是Unicode。密码中是否允许使用非ASCII字符?如果是,则仅禁止ASCII空格,或者应排除所有Unicode空格。

默认情况下,\s仅匹配ASCII空格,因此其反\S匹配所有Unicode字符(空白或非空白)和所有非空白ASCII字符。如果允许使用Unicode字符但不包含Unicode空格,则可以指定UNICODE_CHARACTER_CLASS标志以使\S排除Unicode空格。如果不允许使用Unicode字符,则可以使用[\x21-\x7E]代替\S来匹配所有不是空格或控制字符的ASCII字符。

这将我们带到下一个潜在的问题:我们是否想要允许控制字符?编写正确的正则表达式的第一步是准确指定您想要匹配的内容以及您不想要的内容。唯一100%技术上正确的答案是问题中的密码规范是不明确的,因为它没有说明是否允许某些字符范围如控制字符或非ASCII字符。

答案 3 :(得分:8)

你不应该使用过于复杂的正则表达式(如果可以避免它们),因为它们是

  • 难以阅读(至少除了你自己以外的所有人)
  • 难以延伸
  • 难以调试

虽然使用许多小正则表达式可能会有很小的性能开销,但上面的点很容易超出它。

我会这样实现:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}

答案 4 :(得分:2)

感谢所有答案,基于所有答案,但扩展了特殊字符:

@SuppressWarnings({"regexp", "RegExpUnexpectedAnchor", "RegExpRedundantEscape"})
String PASSWORD_SPECIAL_CHARS = "@#$%^`<>&+=\"!ºª·#~%&'¿¡€,:;*/+-.=_\\[\\]\\(\\)\\|\\_\\?\\\\";
int PASSWORD_MIN_SIZE = 8;
String PASSWORD_REGEXP = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[" + PASSWORD_SPECIAL_CHARS + "])(?=\\S+$).{"+PASSWORD_MIN_SIZE+",}$";

单元测试:

enter image description here

答案 5 :(得分:1)

密码要求:

  • 密码长度至少应为八(8)个字符,系统可以支持该字符。
  • 密码必须包含至少两(2)个这些分组中的字符:字母,数字和特殊字符。

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$
    

我测试了它并且有效

答案 6 :(得分:1)

对于对每种角色的最低要求感兴趣的人,我建议对Tomalak接受的答案进行以下扩展:

^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

请注意,这是一个格式化字符串,而不是最终的正则表达式模式。只需将%d替换为所需的最小值:数字,小写,大写,非数字/字符和整个密码(分别)。最大出现次数是不可能的(除非你想要最大值为0,有效地拒绝任何这样的字符),但这些也可以很容易地添加。注意每种类型的额外分组,以便最小/最大约束允许非连续匹配。这为一个系统创造了奇迹,我们可以集中配置我们需要的每种类型的角色,然后让网站以及两个不同的移动平台获取该信息,以便根据上述格式化字符串构建正则表达式模式。 / p>

答案 7 :(得分:0)

接受所有特殊字符(包括_)的更一般的答案会略有不同:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\W|\_])(?=\S+$).{8,}$

差异 (?=.*[\W|\_]) 翻译为“包括下划线在内的所有特殊字符中的至少一个”。

答案 8 :(得分:0)

RegEx是-

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. 至少8位数字{8,}
  2. 至少一个数字(?=。* \ d)
  3. 至少一个小写字母(?=。* [a-z])
  4. 至少一个大写字母(?=。* [A-Z])
  5. 至少一个特殊字符(?=。* [@ ## %% ^&+ =])
  6. 没有空格[^ \ s]

答案 9 :(得分:0)

强密码示例代码块:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. 至少6位数字
  2. 最多18位数字
  3. 一个号码
  4. 一个小写字母
  5. 一个大写字母
  6. 可以包含所有特殊字符

答案 10 :(得分:0)

使用功能强大的API Passay库。

答案 11 :(得分:0)

您也可以这样。

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}

答案 12 :(得分:0)

具有参数的Java方法准备就绪

只需复制并粘贴并设置所需的参数即可。

如果您不需要模块,只需对其注释或添加“ if”(如我对特殊字符所做的操作)

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        

答案 13 :(得分:0)

这个检查每个特殊字符:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$

答案 14 :(得分:0)

String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

<强>解释

  1. 首先将密码设置为字符串并创建整数集o。
  2. 然后检查每个char for for循环。
  3. 如果它在字符串中找到数字,则n添加5.然后跳转到 接下来循环。 Character.isDigit(s.charAt(i))的
  4. 此循环检查放置在字符串中的任何字母。如果它找到了 再添加一个5。 Character.isLetter(s.charAt(i))的
  5. 现在通过if条件检查整数n。如果n = 10则为真 给定的字符串是字母数字,否则不是。

答案 15 :(得分:0)

轻松一个

(“^(?=。* [0-9])(?=。* [az])(?=。* [AZ])(?=。* [\\ W _])[\\ S ] {8,10} $“)

  1. (?=任何) - &gt;表示在所有输入字符串中正向前进,并确保写入此条件.sample(?=。* [0-9]) - &gt;意味着确保在所有字符串中写入一位数字。如果未写入则返回 false                      
  2. (?!任何内容) - &gt;(反之亦然)表示如果条件已写则返回 false 时出现负面向前看。

    关闭意义^(条件)(条件)(条件)(条件) [\ S] {8,10} $

答案 16 :(得分:0)

我认为这也可以做到(作为一种更简单的模式):

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

[Regex Demo]