注册密码校验仅接受@符号?所用密码验证代码问题排查
问题原因
你的密码校验逻辑失效,核心是正则表达式存在两个编写错误,额外还有一处输入处理的隐患:
- 错误使用HTML转义字符
你写的&是XML/HTML场景下对&符号的转义实体,仅在Android布局文件、strings.xml这类XML资源文件中会被解析为单个&字符。直接硬编码在Java代码中时,正则引擎会把它拆成&、a、m、p、;五个独立普通字符,完全无法匹配你预期的&符号。 - 字符集内的
-触发了错误的范围匹配
正则的方括号字符集中,-是专门用来标识ASCII字符范围的元字符,只有放在字符集最开头、或者用反斜杠转义为\-时,才会被识别为普通短横线。你把-写在*和闭合符]之间,Android使用的ICU正则引擎会把它解析为「从到]的ASCII区间」,覆盖了ASCII码42()到93(])的所有字符。你原本定义的合法特殊字符里,!(ASCII 33)、#(35)、$(36)、%(37)、&(38)的码值都小于42,被直接排除在匹配范围外,只有@(ASCII 64)刚好落在这个错误区间内,才会出现只有@能通过校验的现象。 - 输入处理的逻辑隐患
你调用了trim()裁剪密码首尾的空白字符,会擅自篡改用户输入的原始密码内容,如果用户密码首尾本身包含合法字符,会出现实际密码长度、内容和用户输入不一致的问题,导致校验结果不符合预期。
修复方案
- 去掉正则里多余的HTML转义,把
&替换为普通的& - 把字符集里的
-移到最开头,避免被识别为范围元字符 - 去掉
trim()逻辑,保留用户输入的原始密码内容,如果需要提示首尾空格可以单独加判断,不要直接裁剪输入
修复后的校验代码参考:
private Boolean validatePass() { String val = pass.getEditText().getText().toString(); // -放在字符集最开头避免范围歧义,移除了错误的HTML转义 String passwordVal = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[-#?!@$%^&*]).{8,}$"; if (val.isEmpty()) { pass.setError("*Required"); return false; } else if (!val.matches(passwordVal)) { pass.setError("Invalid Password"); return false; } else { pass.setError(null); return true; } }
内容的提问来源于stack exchange,提问作者Earl Andan
相关产品推荐
相关产品推荐

