You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Passay库密码校验:如何禁止紧邻的重复字符序列?

Passay检测紧邻重复字符序列的解决方案

好问题!我刚好对Passay的密码校验规则有不少实践经验,咱们来一步步解决这个问题。

先明确结论:Passay没有内置规则,需要自定义

Passay的核心内置规则里,RepeatCharactersRule确实只能处理单个字符的连续重复(比如aaa这种场景),没法识别abab或者banana里an紧邻重复这类长度≥2的子串重复情况。所以要实现你需要的校验逻辑,得自定义一个规则。

自定义规则的实现思路

核心逻辑很简单:遍历密码中所有可能的子串(长度从2开始,到密码长度的一半,因为要重复两次至少需要2倍子串长度),检查是否存在某个子串和紧接着的同长度子串完全一致。

具体实现代码

首先你的依赖配置没问题,先贴出来方便参考:

<dependencies>
    <dependency>
        <groupId>org.passay</groupId>
        <artifactId>passay</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>

然后是自定义规则类ConsecutiveSubstringRepeatRule,实现Passay的Rule接口:

import org.passay.*;
import java.util.ArrayList;
import java.util.List;

public class ConsecutiveSubstringRepeatRule implements Rule {
    // 可配置的最小重复子串长度,默认是2(比如"aa"、"abab"都会被检测)
    private int minSubstringLength = 2;

    public ConsecutiveSubstringRepeatRule() {}

    public ConsecutiveSubstringRepeatRule(int minSubstringLength) {
        if (minSubstringLength < 2) {
            throw new IllegalArgumentException("最小子串长度不能小于2");
        }
        this.minSubstringLength = minSubstringLength;
    }

    @Override
    public RuleResult validate(PasswordData passwordData) {
        String password = passwordData.getPassword();
        List<RuleResultDetail> errorDetails = new ArrayList<>();
        boolean isPasswordValid = true;

        // 遍历所有可能的子串长度,从配置的最小值到密码长度的一半
        for (int subLen = minSubstringLength; subLen <= password.length() / 2; subLen++) {
            // 遍历每个可能的起始位置,检查当前子串和下一个紧邻的同长度子串是否相等
            for (int i = 0; i <= password.length() - 2 * subLen; i++) {
                String currentSub = password.substring(i, i + subLen);
                String nextSub = password.substring(i + subLen, i + 2 * subLen);
                if (currentSub.equals(nextSub)) {
                    errorDetails.add(new RuleResultDetail(
                        "CONSECUTIVE_SUBSTRING_REPEAT",
                        new String[]{currentSub, String.valueOf(subLen)}
                    ));
                    isPasswordValid = false;
                    // 如果你想找到第一个重复就停止检测,可以取消下面的注释
                    // break;
                }
            }
            // if (!isPasswordValid) break;
        }

        return new RuleResult(isPasswordValid, errorDetails);
    }

    @Override
    public String[] getMessageKeys() {
        return new String[]{"CONSECUTIVE_SUBSTRING_REPEAT"};
    }
}

如何使用自定义规则

把这个规则加到你的PasswordValidator里,搭配其他规则一起使用:

public class PasswordCheckExample {
    public static void main(String[] args) {
        // 初始化校验器,组合自定义规则和其他内置规则
        PasswordValidator validator = new PasswordValidator(
            new ConsecutiveSubstringRepeatRule(), // 检测≥2的紧邻重复子串
            new RepeatCharactersRule(3) // 禁止单个字符连续重复3次及以上
        );

        // 测试你的几个案例
        checkPassword(validator, "apple");
        checkPassword(validator, "banana");
        checkPassword(validator, "123xy123");
        checkPassword(validator, "abab");
    }

    private static void checkPassword(PasswordValidator validator, String password) {
        RuleResult result = validator.validate(new PasswordData(password));
        System.out.printf("密码「%s」校验结果:%s%n", password, result.isValid() ? "✅ 合规" : "❌ 不合规");
        if (!result.isValid()) {
            System.out.println("错误原因:" + validator.getMessages(result));
            System.out.println("---");
        }
    }
}

运行这段代码的输出会是:

密码「apple」校验结果:❌ 不合规
错误原因:[密码包含连续重复的字符 'p' 超过 2 次]
---
密码「banana」校验结果:❌ 不合规
错误原因:[CONSECUTIVE_SUBSTRING_REPEAT]
---
密码「123xy123」校验结果:✅ 合规
密码「abab」校验结果:❌ 不合规
错误原因:[CONSECUTIVE_SUBSTRING_REPEAT]
---

优化:自定义错误提示

如果想要更友好的错误提示,可以在Passay的消息资源文件里添加对应的键值对,比如:

CONSECUTIVE_SUBSTRING_REPEAT=密码包含紧邻重复的子串 '{0}'(长度为 {1}),请修改

这样validator.getMessages(result)就会返回格式化后的友好提示了。

内容的提问来源于stack exchange,提问作者xinxiu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:54:08