用于密码验证的正则表达式 Java

Posted

技术标签:

【中文标题】用于密码验证的正则表达式 Java【英文标题】:Regexp Java for password validation 【发布时间】:2011-04-17 15:53:07 【问题描述】:

我正在创建一个用于密码验证的正则表达式,以在 Java 应用程序中用作配置参数。

正则表达式是:

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

密码策略是:

至少 8 个字符

至少包含一位数字

至少包含一个低位 alpha 字符和一个高位 alpha 字符

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

不包含空格、制表符等

我错过了第 5 点。我无法让正则表达式检查空格、制表符、回车等。

谁能帮帮我?

【问题讨论】:

密码规则不好。请参阅Reference - Password Validation 了解更多信息。 【参考方案1】:

试试这个:

^(?=.*[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])。对于这种长度的正则表达式并为此目的,我不建议这样做,因为它没有真正的好处。

【讨论】:

@Kerby82:在 Java 字符串中,必须转义反斜杠。尝试使用\\s。这是 Java 要求,而不是正则表达式要求。 @Allov 想一想:所有未强制执行的内容都是可选的。只需删除您不想执行的检查。应该很容易根据您的需求调整解决方案。 此答案已添加到Stack Overflow Regular Expression FAQ 的“常见验证任务”下。 @shA.t 是一样的。我只尝试保留(?=...) 模式,以便它与表达式其余部分的设置相匹配.. @shA.t 您说“仅包含非空格字符”((?=\S+$)) 还是“不包含空格字符”((?!.*\s)) 是一个偏好问题。使用任何你喜欢的更好。 :)【参考方案2】:

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

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 个字符

【讨论】:

.5,10 表示最少 5 个字符,最多 10 个字符。以防万一有人在寻找具体的解释。 @iabhi,我在找这个。谢谢。 出于安全考虑,我正在尝试对存储在字符数组而不是字符串中的密码实施正则表达式。但是如何将正则表达式应用于 char 数组? 这也接受(通常)不允许的字符,如“€”或“§”(即:“1q@W€°§ß”)。您应该将最后一个“.8,”替换为允许的字符列表,例如"[@#$%^&+=a-zA-Z0-9]8,"【参考方案3】:

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

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

^(?=.*[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 上一次性使用all 来完成:

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

如果提供的密码确实包含空格,则将完成所有检查,但最终检查失败。这可以通过将所有点替换为\S 来避免:

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

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

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

\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S8,\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 字符)。

【讨论】:

【参考方案4】:

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

难以阅读(至少对除了你自己以外的所有人而言) 难以扩展 难以调试

虽然使用许多小型正则表达式可能会产生很小的性能开销,但上述几点很容易超过它。

我会这样实现:

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;

【讨论】:

从安全角度来看,最好强制使用更长的密码,防止使用众所周知的密码(如 12345 和 pass=user),而不是让密码变得超级复杂且难以记忆。 我喜欢你上面的方法。谢谢你!【参考方案5】:

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

@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+",$";

单元测试:

【讨论】:

【参考方案6】:

密码要求:

密码长度至少应为八 (8) 个字符,系统可以支持它。

密码必须包含至少两 (2) 组中的字符:字母、数字和特殊字符。

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

我测试了它,它可以工作

【讨论】:

【参考方案7】:

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

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

请注意,这是一个格式化字符串,而不是最终的正则表达式模式。只需将 %d 替换为所需的最少出现次数:数字、小写字母、大写字母、非数字/字符和整个密码(分别)。最大出现次数不太可能(除非您希望最大值为 0,从而有效地拒绝任何此类字符),但也可以轻松添加这些字符。请注意围绕每种类型的额外分组,以便最小/最大约束允许非连续匹配。这对于我们可以集中配置所需的每种类型字符的数量然后让网站以及两个不同的移动平台获取该信息以便基于上述格式化字符串构造正则表达式模式的系统产生了奇迹。

【讨论】:

【参考方案8】:

这个检查每个特殊字符:

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

【讨论】:

【参考方案9】:

为您准备好 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;
        

【讨论】:

【参考方案10】:

你也可以这样做。

 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;

【讨论】:

【参考方案11】:

使用强大的api库Passay。

【讨论】:

【参考方案12】:

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

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

[Regex Demo]

【讨论】:

【参考方案13】:

简单的

("^ (?=.* [0-9]) (?=.* [az]) (?=.* [AZ]) (?=.* [\\W_])[\\S ]8,10$")

    (?= anything ) -> 表示在所有输入字符串中正向向前看,并确保为此条件写入 .sample(?=.*[0-9])-> 表示确保将一位数字写入all string.if notwritten return false .

    (?! 任何东西) ->(反之亦然) 表示如果条件为 written 返回 false

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

【讨论】:

虽然只有代码的答案可能会为问题提供解决方案,但一些解释会大大提高答案的质量。【参考方案14】:
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>");

说明:

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

【讨论】:

【参考方案15】:

强密码示例代码块:

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

【讨论】:

【参考方案16】:

正则表达式是 -

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

【讨论】:

【参考方案17】:

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

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

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

【讨论】:

以上是关于用于密码验证的正则表达式 Java的主要内容,如果未能解决你的问题,请参考以下文章

用于密码验证的正则表达式 [重复]

用于密码验证的正则表达式,仅特定字符 [重复]

java中的正则表达式问题 怎么验证密码必须由字母 数字或下划线开头,密码可以随便组合

JAVA正则验证[密码]。验证规则:[5-20位字符,英文,数字或各种符号,不能存在单一形式]。 答案如下:

简化 java 正则表达式代码以验证密码

JAVA密码校验正则表达式