0

我正在使用以下正则表达式。(?=.+[az])(?=.+[AZ])(?=.+[^a-zA-Z]).{8,}

我的目标是拥有一个具有以下 4 个属性中的 3 个的密码

大写字符、小写字符、数字、特殊字符

我正在使用http://rubular.com/r/i26nwsTcaUhttp://regexlib.com/RETester.aspx使用以下输入来测试表达式

P@55w0rd
password1P
Password1
paSSw0rd

所有这些都应该通过,但只有第二个和第四个通过http://rubular.com/r/i26nwsTcaU并且所有这些都通过http://regexlib.com/RETester.aspx

我还有以下用于验证的代码

private void doValidate(String inputStr,String regex) {
    Pattern pattern = Pattern.compile(regex);
    if(!pattern.matcher(inputStr).matches()){
        String errMessage = "";
        throw new UniquenessConstraintViolatedException(errMessage);
    }
}

此代码无法验证应该通过的“Password1”。就表达而言,我是这样理解的

must have lower (?=.+[a-z])
must have upper (?=.+[A-Z])
must have non alpha (?=.+[^a-zA-Z])
must be eight characters long .{8,}

谁能告诉我我做错了什么。

提前致谢。

4

4 回答 4

1

本质上,.+子表达式是罪魁祸首,它们应该是.*. 否则,前瞻部分会查找小写、大写或非字母,但如果每个相应类型的字符是字符串中的第一个字符,则不计算在内。因此,您验证的不是密码,而是第一个字符被截断的密码。虽然@Cfreak 不对,但他很接近 - 使用普通的正则表达式无法实现您正在做的事情,您必须使用他的建议。使用前瞻组 - (?=)- 可以做您需要的事情。不过,就我个人而言,我宁愿像@Cfreak 建议的那样对其进行编码——它更具可读性,并且您的意图从代码中也更加清晰。复杂的正则表达式往往难以编写,但在一段时间后几乎无法阅读、调试或改进。

于 2012-05-11T18:34:20.757 回答
0

您的正则表达式现在说您必须有 1 个或多个小写字符,后跟 1 个或多个大写字符,然后是 1 个或多个大写或小写字符,然后是 8 个或更多字符。

除非您指定特定字符出现的位置,否则正则表达式不能执行 AND。您基本上需要将正则表达式的每个部分拆分为自己的正则表达式并检查每个部分。您可以使用 Java 具有的任何字符串长度方法检查长度(对不起,我不是 Java 开发人员,所以我不知道这是什么问题)。

伪代码:

if( regexForLower && regexForUpper && regexForSpecial && string.length == 8 ) {
     // pass
}
于 2012-05-11T18:18:10.800 回答
0

正如我在评论中所说,位置 0 大写字母被忽略。

这是一个所有四个密码都匹配的正则表达式。

(?=.+\\d)(?=.+[a-z])(?=\\w*[A-Z]).{8,}
于 2012-05-11T18:22:15.980 回答
0

我不会使用这样的正则表达式。

  • 很难理解
  • 难以调试
  • 难以扩展
  • 你对它的结果无能为力

如果您想告诉客户他的密码有什么问题,您必须再次调查密码。在现实世界环境中,您可能希望支持来自外国语言环境的字符。

import java.util.*;
/**
    Pwtest

    @author Stefan Wagner
    @date Fr 11. Mai 20:55:38 CEST 2012
*/
public class Pwtest
{

    public int boolcount (boolean [] arr) {
        int sum = 0;
        for (boolean b : arr) 
            if (b) 
                ++sum;
        return sum;
    }

    public boolean [] rulesMatch (String [] groups, String password) {
        int idx = 0;
        boolean [] matches = new boolean [groups.length];
        for (String g: groups) {
            matches[idx] = (password.matches (".*" + g + ".*"));
            ++idx;
        }
        return matches;     
    }

    public Pwtest ()
    {
        String [] groups = new String [] {"[a-z]", "[A-Z]", "[0-9]", "[^a-zA-Z0-9]"};
        String [] pwl = new String [] {"P@55w0rd", "password1P", "Password1", "paSSw0rd", "onlylower", "ONLYUPPER", "1234", ",:?!"};
        List <boolean[]> lii = new ArrayList <boolean[]> ();
        for (String password: pwl) {
            lii.add (rulesMatch (groups, password)); 
        }

        for (int i = 0 ; i < lii.size (); ++i) {
            boolean [] matches = lii.get (i); 
            String pw = pwl[i];
            if (boolcount (matches) < 3) {
                System.out.print ("Password:\t" + pw + " violates rule (s): ");
                int idx = 0; 
                for (boolean b: matches) {
                    if (! b) 
                        System.out.print (groups[idx] + " "); 
                    ++idx;
                }
                System.out.println (); 
            }
            else System.out.println ("Password:\t" + pw + " fine ");
        }
    }

    public static void main (String args[])
    {
        new Pwtest ();
    }
}

输出:

Password:   P@55w0rd fine 
Password:   password1P fine 
Password:   Password1 fine 
Password:   paSSw0rd fine 
Password:   onlylower violates rule (s): [A-Z] [0-9] [^a-zA-Z0-9] 
Password:   ONLYUPPER violates rule (s): [a-z] [0-9] [^a-zA-Z0-9] 
Password:   1234 violates rule (s): [a-z] [A-Z] [^a-zA-Z0-9] 
Password:   ,:?! violates rule (s): [a-z] [A-Z] [0-9] 
Password:   Übergrößen345 fine 
Password:   345ÄÜö violates rule (s): [a-z] [A-Z]
于 2012-05-11T19:51:52.827 回答