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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3802192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:11:29  来源:igfitidea点击:

Regexp Java for password validation

javaregex

提问by Kerby82

I'm creating a regexp for password validation to be used in a Java application as a configuration parameter.

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

The regexp is:

正则表达式是:

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

The password policy is:

密码策略是:

  • At least 8 chars

  • Contains at least one digit

  • Contains at least one lower alpha char and one upper alpha char

  • Contains at least one char within a set of special chars (@#%$^etc.)

  • Does not contain space, tab, etc.

  • 至少 8 个字符

  • 至少包含一位数字

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

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

  • 不包含空格、制表符等。

I'm missing just point 5. I'm not able to have the regexp check for space, tab, carriage return, etc.

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

Could anyone help me?

有人可以帮助我吗?

采纳答案by Tomalak

Try this:

尝试这个:

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

Explanation:

解释:

^                 # 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

It's easy to add, modify or remove individual rules, since every rule is an independent "module".

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

The (?=.*[xyz])construct eats the entire string (.*) and backtracks to the first occurrence where [xyz]can match. It succeeds if [xyz]is found, it fails otherwise.

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

The alternative would be using a reluctant qualifier: (?=.*?[xyz]). For a password check, this will hardly make any difference, for much longer strings it could be the more efficient variant.

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

The most efficient variant (but hardest to read and maintain, therefore the most error-prone) would be (?=[^xyz]*[xyz]), of course. For a regex of this length and for this purpose, I would dis-recommend doing it that way, as it has no real benefits.

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

回答by agiles

simple example using regex

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

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));
   }
}

Explanations:

说明:

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

回答by Andrew

Password Requirement :

密码要求:

  • Password should be at least eight (8) characters in length where the system can support it.
  • Passwords must include characters from at least two (2) of these groupings: alpha, numeric, and special characters.

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$
    
  • 密码的长度应至少为八 (8) 个字符,系统可以支持它。
  • 密码必须包含至少两 (2) 组中的字符:字母、数字和特殊字符。

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

I tested it and it works

我测试了它并且它有效

回答by shA.t

I think this can do it also (as a simpler mode):

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

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

[Regex Demo]

[正则表达式演示]

回答by Jan Goyvaerts

All the previously given answers use the same (correct) technique to use a separate lookahead for each requirement. But they contain a couple of inefficiencies and a potentially massive bug, depending on the back end that will actually use the password.

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

I'll start with the regex from the accepted answer:

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

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

First of all, since Java supports \Aand \zI prefer to use those to make sure the entire string is validated, independently of Pattern.MULTILINE. This doesn't affect performance, but avoids mistakes when regexes are recycled.

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

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

Checking that the password does not contain whitespace and checking its minimum length can be done in a single pass by using the all at once by putting variable quantifier {8,}on the shorthand \Sthat limits the allowed characters:

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

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

If the provided password does contain a space, all the checks will be done, only to have the final check fail on the space. This can be avoided by replacing all the dots with \S:

如果提供的密码确实包含空格,则将完成所有检查,只会使最后的检查失败。这可以通过将所有点替换为\S

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

The dot should only be used if you really want to allow any character. Otherwise, use a (negated) character class to limit your regex to only those characters that are really permitted. Though it makes little difference in this case, not using the dot when something else is more appropriateis a very good habit. I see far too many cases of catastrophic backtrackingbecause the developer was too lazy to use something more appropriate than the dot.

只有当你真的想允许任何字符时才应该使用点。否则,使用(否定的)字符类将您的正则表达式限制为真正允许的字符。虽然在这种情况下没有什么区别,但在其他更合适的情况下不使用点是一个很好的习惯。我看到太多灾难性回溯的案例,因为开发人员懒得使用比点更合适的东西。

Since there's a good chance the initial tests will find an appropriate character in the first half of the password, a lazy quantifier can be more efficient:

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

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

But now for the really important issue: none of the answers mentions the fact that the original question seems to be written by somebody who thinks in ASCII. But in Java strings are Unicode. Are non-ASCII characters allowed in passwords? If they are, are only ASCII spaces disallowed, or should all Unicode whitespace be excluded.

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

By default \smatches only ASCII whitespace, so its inverse \Smatches all Unicode characters (whitespace or not) and all non-whitespace ASCII characters. If Unicode characters are allowed but Unicode spaces are not, the UNICODE_CHARACTER_CLASSflag can be specified to make \Sexclude Unicode whitespace. If Unicode characters are not allowed, then [\x21-\x7E]can be used instead of \Sto match all ASCII characters that are not a space or a control character.

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

Which brings us to the next potential issue: do we want to allow control characters? The first step in writing a proper regex is to exactly specify what you want to match and what you don't. The only 100% technically correct answer is that the password specification in the question is ambiguous because it does not state whether certain ranges of characters like control characters or non-ASCII characters are permitted or not.

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

回答by Martin Rauscher

You should not use overly complex Regex (if you can avoid them) because they are

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

  • hard to read (at least for everyone but yourself)
  • hard to extend
  • hard to debug
  • 难以阅读(至少对除了你自己之外的每个人)
  • 难以扩展
  • 难以调试

Although there might be a small performance overhead in using many small regular expressions, the points above outweight it easily.

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

I would implement like this:

我会这样实现:

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;
}

回答by Demetrios Christopher

For anyone interested in minimum requirements for each type of character, I would suggest making the following extension over Tomalak's accepted answer:

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

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

Notice that this is a formatting string and not the final regex pattern. Just substitute %d with the minimum required occurrences for: digits, lowercase, uppercase, non-digit/character, and entire password (respectively). Maximum occurrences are unlikely (unless you want a max of 0, effectively rejecting any such characters) but those could be easily added as well. Notice the extra grouping around each type so that the min/max constraints allow for non-consecutive matches. This worked wonders for a system where we could centrally configure how many of each type of character we required and then have the website as well as two different mobile platforms fetch that information in order to construct the regex pattern based on the above formatting string.

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

回答by ibrahem shabban

easy one

简单的

("^ (?=.* [0-9]) (?=.* [a-z]) (?=.* [A-Z]) (?=.* [\\W_])[\\S]{8,10}$")

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

  1. (?= anything ) ->means positive looks forward in all input string and make sure for this condition is written .sample(?=.*[0-9])-> means ensure one digit number is written in the all string.if not writtenreturn false.
  2. (?! anything ) ->(vise versa) means negative looks forward if condition is writtenreturn false.

    close meaning ^(condition)(condition)(condition)(condition)[\S]{8,10}$

  1. (?= any ) -> 表示在所有输入字符串中正向查找并确保写入此条件 .sample(?=.*[0-9])-> 表示确保在所有字符串中写入一位数字。如果不写返回false
  2. (?! 任何东西) ->(反之亦然) 表示如果条件写入返回false则为负期待。

    接近的意思 ^(condition)(condition)(condition)(condition) [\S]{8,10}$

回答by Naresh Babu

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>");
}

Explanation:

解释:

  1. First set the password as a string and create integer set o.
  2. Then check the each and every char by for loop.
  3. If it finds number in the string then the n add 5. Then jump to the next for loop. Character.isDigit(s.charAt(i))
  4. This loop check any alphabets placed in the string. If its find then add one more 5 in n. Character.isLetter(s.charAt(i))
  5. Now check the integer n by the way of if condition. If n=10 is true given string is alphanumeric else its not.
  1. 首先将密码设置为字符串并创建整数集o。
  2. 然后通过 for 循环检查每个字符。
  3. 如果它在字符串中找到数字,则 n 加 5。然后跳转到下一个 for 循环。Character.isDigit(s.charAt(i))
  4. 此循环检查放置在字符串中的任何字母。如果找到,则在 n 中再增加一个 5。Character.isLetter(s.charAt(i))
  5. 现在通过if条件检查整数n。如果 n=10 为真,则给定字符串是字母数字,否则不是。

回答by Ansu

This one checks for every special character :

这个检查每个特殊字符:

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