# 先锋重置密码后为何登不上？表单悄悄截断了你的密码

**Summary:** Tanin Na Nakorn 发现先锋的密码重置表单静默地将密码截断为20字符，而登录时却提交完整密码。我认为账户恢复完成前，必须明确显示长度错误并确保下次登录成功。

- Canonical: https://markhuang.ai/zh/news/vanguard-password-reset-silent-cutoff
- Language: zh-CN
- Author: [Mark Huang](https://markhuang.ai/about)
- Published: 2026-10-03
- Section: News
- Tags: 先锋, 密码管理器, 账户恢复, Web安全, 表单验证
- Source: [Tanin Na Nakorn](https://tanin.nanakorn.com/input-type-password-maxlength-20-is-considered-harmful-and-why-i-couldnt-login-into-vanguard/)
- License: https://creativecommons.org/licenses/by-nc/4.0/

---

![一串玻璃密码珠被一道狭窄的门隔断，部分凭证留在封闭金库外](https://cdn.markhuang.ai/news/vanguard-password-reset-silent-cutoff/hero.webp)

*概念图展示报告中的故障：重置表单接受了截短的凭证，而用户保留的是原始密码。*

[Tanin Na Nakorn](https://tanin.nanakorn.com/about/)在[2026年10月2日](https://tanin.nanakorn.com/input-type-password-maxlength-20-is-considered-harmful-and-why-i-couldnt-login-into-vanguard/)讲了自己登录先锋账户失败的经过：密码重置明明成功了，接下来却怎么也用刚复制的密码登不上去。他查出来原因是两个表单不一致——重置页面的密码字段限长20个字符，登录页面却没有这个限制。

让我更不舒服的不是20字符的限制，而是那个"成功"提示。重置完密码，我当然期望自己选的密码能直接登录。可按Na Nakorn描述的流程，表单悄悄把他粘贴的内容截短了，然后告诉他"重置成功"。等到登录页面报密码错误，他得自己琢磨到底是哪里出了问题——原来重置时交出去的已经是另一个值了。

以上是他对自己账户网页流程的记录。目前不清楚有多少账户受到同样影响，也不知道先锋是否已经改了表单。不过这件事给开发者提了一个具体的醒：两个密码字段可以彼此一致，却跟用户手里保存的密码对不上。

## 两个确认字段可能同时出错

Na Nakorn说他用1Password生成了一个超过20字符的密码，然后复制粘贴到新密码和确认密码两个框里。Chrome把粘贴的内容截到了`maxlength`的上限。两个截短后的值一样，重置也就通过了。等到登录时，他把完整密码粘贴到没有长度限制的字段里，结果被告知密码错误。

[MDN的密码输入文档](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/password)把`maxlength`定义为最大输入长度，用UTF-16代码单元计算。没加这个属性的字段就没有长度限制。这正好解释了为什么两个表单收到的值不一样。但这说明不了先锋是怎么存密码的。

```mermaid

flowchart TD
    A[原始密码超过20个字符] --> B[粘贴到重置和确认字段]
    B --> C[两个字段保留截短后的值]
    C --> D[重置报告成功]
    A --> E[将原始密码粘贴到登录字段]
    D --> E
    E --> F[登录提交完整值]
    F --> G[密码错误响应]
```

这张图就是按他描述的流程画的。一个HTML属性说明不了先锋用了什么哈希算法，更不能推断它是明文存密码。Na Nakorn还提到他可以用手机App扫二维码登录，但那走的是另一条认证通道，也看不出App那边是否接受更长的密码。

## 合理的限制仍需诚实的拒绝

[Hacker News上对这篇文章的讨论](https://news.ycombinator.com/item?id=49939773)里有个挺有意思的分歧。有人质疑生成的密码为什么要这么长；也有人觉得输入长度确实该有上限，但这个20字符的限制太小了，而且表单根本没把限制说清楚。我同意服务方需要控制输入，可这并不能解释为什么表单要悄悄截短而不是直接拒绝。

[OWASP认证备忘单](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md)建议密码上限至少放到64个字符，好让用户能用密码短语。同时也提到，某些哈希实现在遇到超长密码时可能被拖垮，造成拒绝服务。这两条建议合在一起，说明设一个合理的上限完全没问题。但同一份指南也明确说了：不要悄悄截断密码，并且要允许用户在认证字段里粘贴。

他的密码到底该多长，我不需要下结论也能看出问题。他选了一个密码，记下来了，然后通过一个偷偷改了它的表单提交。如果表单当时就拒绝，他完全可以换个能用的密码保存下来。可静默截断让他以为一切正常，直到登录时才发现不对劲。

理想做法是：表单保留用户粘贴的完整内容，在提交前就告诉用户密码超长了，服务器端也执行同样的规则。光去掉`maxlength`并不能保证一致性——注册、重置、登录三个环节都得对用户实际输入的密码执行同一套策略。

## 我会在重置后测试登录

如果让我来审这个流程，我会把"重置后第一次登录"加进账户恢复的测试用例里。只测到"重置成功"页面就收工，肯定抓不到Na Nakorn遇到的这种问题。用户选好的密码，必须能在随后的正常登录流程中用得上。

具体来说，要在文档声明的长度边界附近测试粘贴，包括刚好超限的值。超长的尝试应该得到明确拒绝，而不是拿着截短后的密码"成功"重置。密码管理器自动填充也要单独测一遍——不能想当然地认为它跟手动粘贴行为一样。以上是我建议的测试项，我并没有真的拿去跑先锋的表单。

如果你遇到了同样的问题，我建议先去看网站公布的密码要求，再重新走一遍重置流程。如果你设的密码超过了网站说的长度上限，就按那个限制重新生成一个，存进密码管理器，然后马上用新密码登录确认能用。如果还是对不上，就联系客服。用户不应该自己去改页面代码，也不该猜密码到底被截到了第几位。

我在[讨论通行密钥托管和恢复的那篇文章](https://markhuang.ai/news/passkeys-stop-password-phishing-key-custody)里提过一个相关问题：当常用的登录方式失效时，用户得知道怎么找回自己的账户。这件事的道理更简单——既然密码重置告诉你"成功了"，那用户手里记着的那个密码就应该能登上去。
