【问题标题】:How to match 1 character in a string如何匹配字符串中的 1 个字符
【发布时间】:2013-07-12 07:11:10
【问题描述】:

我正在为密码策略编写代码。

政策规定您不能使用已使用的相同字母。 例如:密码 - 您不能使用密码,因为它有两个 's'

我该怎么做?

编辑:

这是我的完整实现:​​

private static final String PASSWORD_DUPLICATE_CHARACTERS = "^(?:([a-zA-Z])(?!.*\\1))$";

pattern = Pattern.compile(PASSWORD_DUPLICATE_CHARACTERS);
this.checkForDuplicateLetters(LDAPNewUserPassword);

private boolean checkForDuplicateLetters(final String newPassword) throws LDAPException{
    LoggingEnt userEnt = new LoggingEnt();
    String userid = userEnt.getUseridCode();
    boolean foundDuplicate = false;

    matcher = pattern.matcher(newPassword);

    if (newPassword.matches(PASSWORD_DUPLICATE_LETTERS)){
        foundDuplicate = true;
        userEnt.setMsg1("Duplicate.");
        throw new LDAPException("Invalid password combination for " + userid, LDAPException.INVALID_CREDENTIALS);//BAristo
    } else {
        userEnt.setMsg1("Your password has been successfully changed.");
    }

    return matcher.matches();

}

【问题讨论】:

  • 这是您唯一的限制吗?或者您是否在单独的规则中实施了多个限制?
  • 应该提一下,这对于密码策略来说不是一个好主意,因为它大大减少了搜索空间。
  • @Tim Pietzcker 没有。我已将其分解为几个序列,以使其他程序员在我离开后仍能阅读代码。

标签: java regex string character match


【解决方案1】:

使用这个正则表达式:

private static final String PASSWORD_PATTERN_LOWER_8 = "^(?:([a-zA-Z])(?!.*\\1))$";

【讨论】:

  • 这个正则表达式的好处是它可以在字符串的任何地方找到重复的字母。另一方面,它现在只允许密码中的字母,甚至允许空字符串...
  • 好点,但您也可以在匹配字符类中添加更多字符以及最小匹配数。根据 OP 问题,我正在显示没有额外限制的正则表达式。
  • 小写字母即使没有重复字母也不会被读取。请帮帮我。还有其他方法吗?
  • 为我工作。此正则表达式的密码也有 6 个字符的最小限制。如果不需要,请删除 {6,}。
  • 'Pasw70rd' 和 'password' 在您提供的正则表达式上失败。一个没有重复,另一个有,但都失败了。
【解决方案2】:

我会用这样的东西

^((.)(?!.*\1))+$

这将匹配字符串中没有重复字符的字符串

【讨论】:

    【解决方案3】:

    您可以使用negative lookahead assertion,如下所示:

    <snip> PASSWORD_PATTERN_LOWER_8 = "(?i)^(?!.*(.).*\\1)";
    

    说明:

    (?i)  # Case-insensitive mode
    ^     # Match start of string (might be redundant, but won't hurt either)
    (?!   # Assert that it's impossible to match...
     .*   # any string
     (.)  # that's followed by one character (captured into group 1)
     .*   # followed by any string
     \\1  # and a repetition of the character we captured before.
    )     # End of lookahead
    

    性能不会那么好,尤其是对于较长的字符串,因为在最坏的情况下,每个字符都必须与其他每个字符进行比较。

    例如,密码.qwertzuiopasdfghjklöäyxcvbnm,. 只会在正则表达式引擎超过 1000 步后被检测为无效,而qwertzuiopasdfghjklöäyxcvbnm,.. 会立即失败。

    最好先对字符串进行排序,然后直接查找后续字符:

    <snip> PASSWORD_PATTERN_LOWER_8 = "(?i)^(?!.*(.)\\1)";
    

    【讨论】:

    • 不必是后续相同的字符。另一个例子是“姐姐”。如果“S”已经被使用,则不能再使用。
    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    • 2022-01-02
    • 2022-11-30
    相关资源
    最近更新 更多