先说我们的建议。 Proxy Mail QA 是我们做的,所以我们并不中立,但它不替你选择密码策略。下面的数字来自 NIST 的数字身份指南(SP 800-63B 第四版),很多安全团队都遵循它。我们推荐在你做出决定之后的那一步使用 Proxy Mail QA:用恰好等于最小值和最大值、各差一位以及包含各类符号的测试密码,检查你的表单和服务器是否真的按你的决定执行。它不审查你的密码存储方式,也不审查你的整体安全。
简短的答案
- 如果密码是登录所需的唯一凭据,至少 15 个字符。
- 如果每个账号还有第二因素(如身份验证器应用的验证码),至少 8 个字符。
- 允许至少 64 个字符。 更长也可以,但上千的上限没有必要。
- 不要强制要求大写字母、数字和符号。 长度更重要,而这些规则会让人选择
Password1!。 - 拒绝常见和已泄露的密码,把新密码与一个列表进行比对。
其余指南,用平实的话说
NIST 对用户自选密码的指南还提到:
- 接受任何字符:字母、数字、符号、空格和其他语言的字符。在哈希之前对 Unicode 做规范化(NFC),这样用两种方式输入的
é会被视为同一个密码。 - 检查长度时按字符计数,而不是按字节。
- 不要截断密码。 检查整个密码,绝不只检查开头部分。
- 不要强制定期更换密码。 只有在有迹象表明密码已泄露时才要求更换。
- 不要密码提示,也不要安全问题。
- 允许粘贴和密码管理器,让人们无需手动输入就能使用较长的随机密码。
- 应要求显示已输入的内容,让人们在提交前检查较长的密码。
为什么还要有最大长度?
很长的密码会占用服务器的哈希时间,所以最大长度可以防止有人发送数 MB 的内容作为密码。把它设得远高于人们实际使用的长度:NIST 建议至少允许 64 个字符,128 或 256 也很常见。
注意你的哈希算法。bcrypt 只读取密码的前 72 个字节,忽略其余部分。于是两个开头相同的长密码可以互相登录对方的账号。一个字符可能不止一个字节(é 是两个,emoji 是四个),所以 72 个字节可能少于 72 个字符。可以选择:
- 使用 Argon2id(或 scrypt),它没有这种限制,或者
- 把最大长度设在 72 个字节以内能容纳的长度,或者
- 如果必须用 bcrypt 并支持更长的密码,先用安全团队认可的方式对密码做一次哈希。
把规则放在浏览器能看到的地方
<label for="password">Password</label><p id="password-rules">At least 15 characters. Any letters, numbers, symbols or spaces.</p><input id="password" name="password" type="password" autocomplete="new-password" minlength="15" maxlength="128" aria-describedby="password-rules" required />minlength和maxlength能让浏览器提前提示,也能让密码管理器生成符合要求的密码。maxlength还会不加提示地截断粘贴的文本,所以要把它设得远高于密码管理器会生成的长度。autocomplete="new-password"会让密码管理器提供一个新的强密码。- 在用户输入之前就显示规则,而不只是在出错之后。
- 在服务器上执行相同的规则。 浏览器的检查只是为了方便,任何人都能绕过。
- 如果你使用认证服务(Supabase Auth、Clerk、Firebase Authentication、Auth0 等),也要在其设置中设定最小长度。很多服务默认值短得多,页面写着 15 而服务接受 6,是一个常见的 bug。
检查你的表单是否按你的决定执行
get_password_variants(MCP)、qa.passwordVariants()(npm)或 GET /v1/variants/passwords(REST API)接受你的规则(min_length、max_length,以及是否允许 symbols),并返回分为三组的新测试密码:
| 分组 | 按 15 到 64 的策略 | 预期结果 |
|---|---|---|
accept |
恰好 15 个和恰好 64 个字符;每类符号;中间有空格;éüñ |
被接受,之后能按输入原样登录 |
reject |
14 个字符;65 个字符 | 被拒绝,在创建账号之前显示相应规则 |
decide |
只有数字;只有小写字母;开头或结尾有空格;一个 emoji;用两种方式输入的 é;前 72 个字节相同的两个密码(当最大长度超过 72 时) |
由你决定,但要有意识地决定。按 NIST 的要求,15 位纯数字密码是允许的,除非它在你的黑名单上 |
最需要注意的是 72 字节的那一对:如果第二个密码能登录用第一个密码创建的账号,说明你的应用在截断密码。
你可以手动运行、通过智能体运行,或放在测试中运行:
- 手动: 使用 Proxy Mail QA for Chrome,密码字段中的卡片会提供 Edge-case password,其中有标为“Should be accepted”和“Should be rejected”的列表,并按该字段自身的
minlength和maxlength生成。它的日常密码也符合这些规则。 - 通过智能体: 在 Qoder 中连接 Proxy Mail QA(Marketplace)后:
Our password policy is 15 to 128 characters, any characters allowed. Using Proxy Mail QA,get_password_variants with min_length 15 and max_length 128, and try each one onhttps://staging.acme.dev/signup with a new test address (use a plus tag for each).For accepted ones, verify the account and sign in with the same password.Give me a table: what it tests, accepted or refused, the message shown, and whethersigning in worked.- 在测试中:
await qa.passwordVariants({ minLength: 15, maxLength: 128 })返回accept、reject和decide,每个都是{ tests, value }列表,可以在 Playwright 或 Cypress 中循环使用。
如果被拒绝的密码完全不显示错误,请见 为什么我的注册表单不显示密码错误?
Proxy Mail QA 在这里不做什么
- 替你选择策略,或告诉你它是否符合你需要遵守的法律或标准。
- 检查密码如何存储,或测试你其他方面的安全。这需要安全审查或渗透测试。
- 测试已泄露密码的黑名单:自己试几个知名的,比如
password1234567。
来源:NIST SP 800-63B-4,以及其中关于 身份验证器 的章节。