
怎么用 String.matches() 判断基础密码规则
Java 里最直接的正则校验方式是 String.matches(),但它默认锚定全字符串(等价于 ^...$),容易误判——比如想检查“是否含数字”,写成 "[0-9]" 会失败,因为没匹配整个串。
- 检测“至少一个数字”:用
s.matches(".*[0-9].*")或更稳妥的Pattern.compile("[0-9]").matcher(s).find() - 检测“必须同时含大小写字母+数字+符号”:别硬塞进一个
matches(),拆成多个find()更清晰、可读性强 -
matches()每次调用都隐式编译正则,高频检测时建议提前用Pattern.compile()缓存
为什么评分算法比布尔判断更实用
用户输“Password123!”和“a1!A”都过得了“强密码”布尔校验,但前者明显更抗爆破。评分制能区分梯度,也方便前端动态反馈(如进度条)。
- 常见加分项:长度 ≥8(+1)、含小写(+1)、大写(+1)、数字(+1)、特殊字符(+1)
- 减分项容易被忽略:连续重复字符(如 "aaa")扣 1 分;常见弱密码子串(如 "password", "123456")扣 2 分
- 别用
switch或一堆if累加——把规则抽成List<function integer>></function>,后期加规则不改主逻辑
正则里 p{Punct} 和 [!@#$%^&*] 差在哪
用户说“要含符号”,你写死 [!@#$%^&*],结果他输 “Passwörd123€” 就不给分——因为 € 不在你列表里,也不在 ASCII 符号范围内。
-
p{Punct}匹配 Unicode 标点(包括 €、¿、。、!等),兼容多语言场景 - 但注意:
p{Punct}也包含中文顿号、书名号等,如果业务只要英文符号,反而该用白名单[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E] - Android 上部分老版本 JDK 对
p{Punct}支持不稳定,生产环境建议实测或降级为 ASCII 白名单
怎么避免空格和不可见字符导致的误判
用户粘贴密码时可能带首尾空格、零宽空格(u200B)、BOM 头,表面看着正常,实际校验全崩。
立即学习“Java免费学习笔记(深入)”;
- 务必在评分前做清理:
s = s.replaceAll("\p{Cf}", "").trim()(p{Cf}清除格式控制符) - 空字符串或纯空白符应直接返回 0 分,而不是让后续规则报
NullPointerException - 调试时加一行日志:
System.out.printf("raw: '%s' → cleaned: '%s'%n", raw, cleaned);,能快速定位粘贴污染问题









