Java使用正则表达式

时间:2010-08-11 21:43:43

标签: java regex

我正在使用重置密码。我需要在java中使用正则表达式来重置密码,这样它就不能包含以前密码中的4个连续字符。

5 个答案:

答案 0 :(得分:4)

我不认为正则表达式是适合此任务的适当工具。

实际上,我看不到任何其他解决方案,然后会尝试找到4个常见字符的子串。

答案 1 :(得分:2)

正则表达式不是解决每个世界问题的方法。如果使用'indexOf'检查将其实现为普通循环,则代码会更简单,更清晰。

修改
我假设您计划在某些应用程序中使用它。如果你只是出于好奇而问,那我就不知道了。)

答案 2 :(得分:2)

你必须动态构建它。假设您之前的密码为“tiddlywinks”。这意味着不允许以下内容:

tidd iddl DDLY dlyw lywi ywin 油墨

恰好如此发生它很好并以4个字符边界结束。没有计划那一个。无论如何。像这样浏览您之前的密码:

public Pattern toValidationExpression( String previousPassword ) {
   StringBuilder builder = new StringBuilder();
   for( int i = 0; i < previousPassword.length()-4; i++ ) {
      if( i > 0 ) builder.append( "|" );
      builder.append( "(" );
      builder.append( previousPassword.substring(i, Math.min( i+4, previousPassword.length() );
      builder.append( ")" );
   }
   return Pattern.compile( builder.toString() );
}

答案 3 :(得分:1)

通过一些合理的限制,这实际上可以通过正则表达式轻松完成。

假设\n是密码的非法部分(非常合理的限制),那么以下代码将非常可读地进行检查(如果您知道如何阅读正则表达式):

static boolean legalChange(String before, String after) {
    String joined = String.format("%s\n%s", before, after);
    return !joined.matches(".*(.{4}).*\n.*\\1.*");
}

这是一个测试工具(see also on ideone.com):

    String[][] tests = {
        { "abcdef", "ghijklm" },                // true
        { "abcdef", "xbcdeyz" },                // false
        { "abcdef", "fedbcda" },                // true
        { "xyz", "" },                          // true
        { "0123456789", "abc123def456ghi" },    // true
        { "0123456789", "abc123456ghi" },       // false
    };
    for (String[] test : tests) {
        System.out.println(legalChange(test[0], test[1]));
    }

请注意,此正则表达式仅检查“no common substring of length 4”规则。还必须有其他密码正则表达式规则。


如何运作

基本上我们将两个字符串组合成一个字符串,由\n分隔(无论如何,这也是用户名中的非法字符。)

然后,此正则表达式将匹配 ILLEGAL 更改:

   before | after              i.e. before = .* (.{4}) .*
          |                         after  = .*   \1   .*
.*(.{4}).*\n.*\1.*
  \____/
    1

也就是说,我们将(.{4})中的before与{1}}匹配并捕获到第1组,然后使用反向引用\1来查看它是否可以在after中匹配。我们将.*放在这两个周围以允许在任何地方发生。正则表达式引擎将对.*进行所有必要的回溯,以查看此模式是否匹配。

由于该模式与 ILLEGAL 更改匹配,因此我们使用matches补码运算符boolean否定!的结果。

这不是解决问题的最有效方法,但假设密码长度合理,速度不会成为问题。

参考

答案 4 :(得分:0)

因此,假设您使用char []而不是String来存储旧/新密码有点安全。安全专家有更好的工具......加密/哈希/等...用于密码管理。

所以,这里是:

/**
 * Compare old to new password to a repeating 4char sequence.
 * -> require passNew to be >= 4char sequence, else return false.
 * -> require passOld to be >= 4char sequence, else return true.
 * -> utilize shifting long to handle full 16Bit char range.
 * -> does not support char beyond 16Bit char range... e.g. codepoint > 2^16.
 * -> codepoint > 2^16 support could be done with XOR 4 codepoints with 8bit shifts
 * @return success true if passNew >= 4char sequence,
 *    passOld lessthan 4char sequence or
 *    normal... 4char sequence not found.
 */
public final boolean validatePassword(char[] passOld, char[] passNew) {
    if (passNew.length lessthan 4) {
        return (false);
    } else if (passOld lessthan 4) {
        return (true);
    }
    long patOld = ((passOld[0] & 0x0ffL) leftshift 32) |
        ((passOld[1] & 0x0ffL) leftshift 16) |
        (passOld[2] & 0x0ffL);
    long patNewOrig = ((passNew[0] & 0x0ffL) leftshift 32) |
        ((passNew[1] & 0x0ffL) leftshift 16) |
        (passNew[2] & 0x0ffL);
    long patNew;
    int offOld = 2, lenOld = passOld.length
    int offNew = 2, lenNew = passNew.length;
    while (++offOld lessthan lenOld) {
        patOld = (patOld leftshift 16) | (passOld[offOld] & 0x0ffL);
        patNew = patNewOrig;
        offNew = 2;
        while (++offNew lessthan lenNew) {
            patNew = (patNew leftshift 16) | (passNew[offNew] & 0x0ffL);
            if (patOld == patNew) {
                return (false);
            }
        }
    }
    return (true);
}