返回探索
指南VibeFix 编辑部更新于 2026年11月3日

别再只拦“长度不够”:vibe 项目的密码强度与泄露密码检查实战

“Password123!”能通过绝大多数密码规则,却也是泄露密码库里的常客。长度和字符种类衡量的是密码的形状,不是稀缺性。本指南讲注册与改密那一刻该做的两件事:按猜测次数评估真实强度,以及用 k-匿名查询检查密码是否已泄露——只发哈希前 5 位,完整密码绝不离境。

一双手在笔记本电脑键盘上打字,示意用户正在输入密码

先讲一个反常识的事实:通过规则的密码,可能早就泄露了

大多数产品的密码规则长这样:至少 8 位,含大小写字母、数字和特殊字符。按这套规则,“Password123!”是满分密码:长度够、种类全、没有连续重复。然而它也是泄露密码库里的常客——成千上万的人都用过它,攻击者拿到泄露库后,第一个试的就是它。规则拦住了“123456”,却放过了“看起来复杂、实际上人人都在用”的密码。这就是只做长度和字符种类检查的根本缺陷:它衡量的是密码的“形状”,不是密码的“稀缺性”。

本文讲的是注册和改密那一刻应当做的两件事:评估密码的真实强度,以及检查它是否已经出现在已知泄露事件里。示例里出现的产品“青竹笔记”和人物“阿棠”均为虚构,仅用于把流程讲具体。先划清与本站已发指南的边界:双因素验证篇讲的是密码之外的第二把锁,Magic Link 篇讲的是不用密码的登录方式,密码找回篇讲的是丢了密码怎么办,密钥轮换篇讲的是第三方 API 密钥。本篇只讲注册与改密那一刻的口令质量关:用户正在输入的这个密码,到底够不够好、是不是已经泄露。

强度评估:别算熵,算“攻击者要猜几次”

教科书式的强度算法是算熵:字符集越大、长度越长,熵越高。但熵有一个致命的盲点:它假设密码是随机生成的,而真实密码几乎从来不是。用户密码的真实结构是:一个熟悉的词,加一点变形,再加几个数字或符号。“Tr0ub4dor&3”按熵公式得分不低,但攻击者根本不需要穷举整个字符空间——他们有字典、有常见变形表、有键盘序列库、有年份和名字库。按猜测次数算强度,才是贴近攻击现实的算法。

业界常用的做法,是借鉴 zxcvbn 这类开源评估器的思路:把密码拆成若干模式片段,分别估算每个片段的猜测成本,再综合成一个强度分级。具体要覆盖的模式至少包括五种:常见词和人名(字典词、品牌名、球队名);键盘序列(qwerty、1qaz、zxcvbn 本身就是键盘路径);日期和年份(生日、纪念日、当前年份);重复与简单变形(aaa、abcabc、把 o 换成 0、末尾加感叹号);上下文相关词(产品名、公司名、用户名本身)。一个密码如果主要由这些片段拼成,哪怕长度达到 12 位,猜测次数也可能只有几万次——在离线破解面前,这连一秒都撑不住。

分级与文案同样重要。建议用四档:弱、一般、强、很好,并且每一档都配一句可操作的改进建议,而不是只给一个颜色条。弱密码的文案应当是“这个密码很常见,换一个你没在别处用过的句子试试”;一般密码应当指出具体弱点,比如“去掉了年份会更好”;强密码也不要只说“很好”,而是提醒“别在别的网站重复用它”。强度条本身不是目的,让用户在不挫败的前提下换一个更好的密码,才是目的。

还有一条容易被忽略的规则:密码里不应当出现用户名、邮箱前缀和产品名。很多产品只检查“密码不能等于用户名”,却放过了“密码包含用户名”的情况。攻击者拿到邮箱地址后,第一个变体就是把它拼进密码猜测里。检查应当是“包含即拒绝”,并且提示文案要写清楚原因,否则用户会以为系统出了 bug。

泄露检查:用前 5 位哈希查全库,但绝不交出完整密码

泄露检查的核心技术,叫 k-匿名查询。流程是这样的:浏览器或服务端先对用户输入的密码做 SHA-1 哈希,只把哈希的前 5 位字符发给泄露库服务,服务返回所有以这 5 位开头、约 800 条左右的哈希后缀,客户端在本地比对完整哈希是否在其中。整个过程中,完整的密码和完整的哈希都没有离开用户的设备或你自己的服务器,服务方只能知道“有人在查某个以这 5 位开头的密码”,而无法反推出是哪一个。

这个流程有几个必须守住的实现细节。第一,查询应当在服务端完成,或者至少在服务端再校验一次——只靠前端检查等于把规则写在用户能改的地方,攻击者绕过它只需要关掉一段脚本。第二,绝不要把用户输入的明文密码、完整哈希写进日志、错误上报或分析系统;日志里一旦出现密码哈希,等于给泄露库又添了一批素材。第三,泄露库本身要定期更新,并且要注明数据来源口径:你查的是“出现在已知泄露事件中的密码”,不是“正在被攻击者使用的密码”,两者不能混为一谈。

一个常见的实现错误,是把泄露检查做成“注册时唯一的一次检查”。正确的做法是三个时点都查:注册时、改密时、以及用户登录后定期复查存量密码。后者尤其重要:一个注册时干净的密码,可能在两年后因为某次第三方泄露而变脏。复查时不要粗暴地把用户踢下线,正确的做法是在用户下次登录后,用一条不吓人的提示告诉他:“你正在用的这个密码曾出现在一次数据泄露事件中,建议你换一个”,并给他一个一键直达改密页的入口。

被查出泄露时,怎么说才既诚实又不吓人

泄露提示的文案,是这套功能里最容易写坏的地方。太轻了,用户不当回事;太重了,用户以为自己的账号已经被盗。建议的文案结构是三句话:事实、影响、行动。事实是“这个密码曾出现在一次已知的数据泄露事件中”;影响是“这意味着别人可能已经见过它,用它登录你的账号会更容易”;行动是“换一个你没在别处用过的密码,开启双因素验证会更稳妥”。

有三句话不要写。不要写具体的泄露事件名称和时间,除非你能百分之百确认对应关系——泄露库只能证明“这个密码出现过”,不能证明“就是在那次事件里泄露的你的密码”。不要写“你的账号已被入侵”——泄露检查查的是密码,不是账号状态,混淆两者会制造不必要的恐慌和客服工单。不要在用户拒绝更换时反复弹窗施压——提醒一次、提供入口、记录状态就够了,反复拦截只会把用户推向“随便设一个应付过去”的行为。

还有一个策略问题:查出泄露的密码,是“禁止使用”还是“警告但放行”?对注册和改密场景,建议直接禁止——用户正在设置新密码,换一个的成本最低,没有放行的理由。对存量密码复查场景,建议警告加引导——用户正在正常使用产品,强制登出改密的打扰成本很高,分级处理更合理。两个场景用同一套策略,是很多产品在这里犯错的根源。

不要做的五件事:比“做什么”更重要的清单

第一,不要明文存储密码,也不要用可逆加密“保护”密码。正确做法是使用专门的密码哈希算法(如 Argon2id 或 bcrypt)加随机盐,并且把哈希参数写进你的安全基线文档,定期复核是否需要升级。第二,不要自创密码规则,比如“必须含一个特殊字符且不能连续出现两个数字”——这类规则只会把用户推向可预测的变形(末尾加一个感叹号),对攻击者毫无阻碍。

第三,不要强制用户定期更换密码,除非有泄露证据。美国国家标准与技术研究院(NIST)的数字身份指南早已不再推荐定期强制更换:它带来的唯一确定效果,是用户把密码改成“旧密码加 1”。正确的做法是“有证据才要求更换”,而泄露检查正是提供证据的机制。第四,不要把密码强度检查只做在前端——前端是体验,后端是防线,两者缺一不可。

第五,不要在密码字段旁边显示“密码强度:弱”之后,就把用户晾在那里。强度评估的输出必须配改进建议,而且建议应当具体到这个密码本身:指出它是哪种模式(常见词、键盘序列、年份),而不是给一句通用的“请使用更复杂的密码”。用户不是不愿意设好密码,大多数时候是不知道自己的密码为什么不好。

落地清单:注册与改密页的验收标准

最后给一份可以直接拿去验收的清单。密码输入框是否有实时的强度评估,并且评估基于猜测次数而非单纯长度?强度文案是否指出了具体弱点并给出改进方向?密码是否禁止包含用户名、邮箱前缀和产品名?注册与改密时是否都做了泄露检查,并且查询只发送哈希前 5 位?服务端是否独立复核了前端的检查结果?日志与错误上报里是否绝无明文密码和完整哈希?存量密码是否有定期复查机制,复查命中时是否用“事实、影响、行动”三句话提示?查出泄露的新密码是否直接禁止,存量密码是否警告加引导?是否没有强制定期更换密码的规则?

这份清单里的每一项,单独看都不难,难的是全部同时做到。密码环节的安全从来不是某一个算法的胜利,而是注册、改密、登录、复查四个时点上,一系列小决定的总和。把“这个密码是不是已经泄露”变成每次设置密码时的默认检查,成本只是一次哈希查询,换来的却是整个账号体系里最便宜的一道防线。

管理员视角:如何在不惹恼全员的情况下推行

密码规则最难的部分往往不是技术,而是推行。管理员如果一夜之间把全员的旧密码全部判为不合格、强制所有人当天改密,第二天收到的不会是感谢,而是成堆的求助工单和“随便设一个应付过去”的新弱密码。更稳妥的推行顺序分四步:第一步,只对新注册和主动改密的用户启用强度评估与泄露检查,老用户不受影响;第二步,对存量密码做静默复查,只统计、不打扰,先拿到“有多少账号用了已泄露密码”这个数字;第三步,向命中泄露的账号定向推送改密提醒,给出两周的宽限期;第四步,宽限期过后,对仍未更换的高风险账号(比如管理员、财务、能访问生产数据的账号)采取分级措施,比如要求下次登录时必须改密。

分级处理的关键,是把“账号的重要性”和“密码的风险”交叉起来看。普通成员用了一个已泄露密码,提醒加引导就够了;能删除生产数据的管理员用了一个已泄露密码,就应当提高处理优先级。反过来,对普通成员采取最严厉的措施,对管理员却放任不管,是安全策略里最常见的本末倒置。推行节奏也应当写进内部公告:什么时候启用、影响谁、不换会怎样,三句话讲清,比事后解释一百句都有用。

密码管理器与通行密钥:把“好密码”变成默认选项

强度评估和泄露检查解决的是“拦住坏密码”,但还有一半问题是“帮用户生成好密码”。密码管理器生成的随机长密码,天然通过强度评估,也极少出现在泄露库里——随机生成的字符串撞上泄露库的概率微乎其微。对产品方来说,最划算的投入,是在注册和改密页上明确支持密码管理器自动填充:不要禁用粘贴,不要用奇怪的输入框结构打断自动填充,不要在密码字段上加干扰性的脚本。很多产品一边要求高强度密码,一边禁用粘贴,等于逼用户只能用自己记得住的弱密码。

更进一步的选择,是提供通行密钥(Passkey)作为替代登录方式。通行密钥用设备本地的密钥对代替口令,从根本上绕过了“密码是否泄露”的问题。但要注意它的定位:通行密钥是登录方式的升级,不是密码检查的替代品。只要产品还保留密码登录入口,密码检查就仍然必要;通行密钥覆盖的用户越多,密码入口的风险面就越小,两者是互补关系,不是非此即彼。已经发布过 Magic Link 与双因素指南的本站读者,可以把这三者理解为同一条线上的不同站点:密码检查管“口令质量”,双因素管“第二道锁”,通行密钥和 Magic Link管“少用口令”。

最后提醒一个移动端细节:手机键盘上的自动填充和密码管理器提示,常常被开发者忽略。如果移动端注册页的密码字段没有正确标记自动填充类型,用户的密码管理器就无法弹出生成建议,用户只能在小键盘上敲一个自己记得住的弱密码。把自动填充类型标对,是一行代码的事,效果却相当于给所有移动端用户默认配了一个密码生成器。

上线前的回归测试:用已知泄露密码验一遍全流程

密码检查功能上线前,应当用一组已知泄露的弱密码把全流程跑一遍回归测试:注册时输入这类密码是否被强度评估判为弱、是否被泄露检查拦截、提示文案是否正确显示;改密时是否同样拦截;存量复查的提醒是否在下次登录时出现、点击后是否直达改密页。测试必须在测试环境用公开的弱密码样本做,绝不能拿真实用户的密码做测试——测试数据里一旦混入真实密码,测试库本身就成了新的泄露源。回归测试的通过标准应当写进发布检查表:任何一处拦截失效、文案错乱或者日志里出现密码痕迹,都应当拦住发布。密码环节的 bug 很少会在测试阶段被发现之后还显得“只是小问题”,因为它守的是整条账号防线的第一道门。

阅读 0评论 0

评论 (0)

ME
0/1000
评论加载中...
浏览项目广场发布你的项目

相关文章

一个人手持手机,桌上放着平板电脑和笔记本电脑,表现多设备登录场景
指南
换了手机也不怕丢账号:vibe 项目的设备与会话管理实战

用户数不清自己的登录会话,产品就要帮他数清楚。本篇只讲登录之后的事:当前设备标记、可改名的设备列表、单台退出、一键退出其他设备、新设备提醒与可疑会话处置,以及一人团队的最小可行集。

应用安全独立开发登录与权限
一只手拿着放大镜查看一叠打印文件,示意对文本来源的核查
资讯
看不见的印记上了更多老模型:Claude 水印扩围,但有一张表还没打勾

Anthropic 从 11 月 3 日起把不可见文本水印扩展到更多老款 Claude 模型,但官方表格与客户邮件口径并不一致:Mythos 5、Opus 4.7、Sonnet 4.6 已打勾,Opus 4.6 的文本水印栏仍是空白。本文按官方表核对了每一项,并讲清检测口子只开给谁、水印到底能证明什么。

AI 编程实践安全与隐私