明文存密码:脱库那天所有用户一起裸奔
发生了什么
应用的数据库将用户密码以明文形式直接存储。当数据库因安全漏洞被攻击者获取后,所有用户的密码一览无余——攻击者无需任何破解,直接就能登录每一个用户的账号。
缺失了哪块知识地图
在搭建用户系统时,没有对密码进行哈希处理,而是把用户输入的原始密码原封不动地存进了数据库。
那天发生了什么
一个小型社区应用上线了。用户注册、登录、发帖,一切看起来都运转正常。开发者很高兴——功能都实现了,AI 帮他把代码写得很顺利。
直到有一天,有人发现数据库暴露在了公网上(也许是配置失误,也许是一个未修补的漏洞)。攻击者下载了整个用户表,打开一看:
| 用户名 | 密码 |
|---|---|
| alice | ilovecats123 |
| bob | P@ssw0rd! |
| charlie | 19950312charlie |
所有密码,清清楚楚,一个不少。
攻击者不需要任何高超的技术,不需要破解任何加密——因为根本就没有加密。他们直接拿着这些密码去试用户的邮箱、社交账号、甚至银行账户。而很多人会在不同网站使用同一个密码——于是一个小应用的漏洞,变成了用户全部数字生活的灾难。
问题出在哪里
这里的核心概念很简单:密码绝对不能以原始文本的形式存储在数据库里。
正确的做法是在存储之前,对密码进行一种叫做"哈希"的单向转换。哈希就像一台绞肉机——你把密码放进去,出来的是一串看起来毫无规律的字符(比如 $2b$10$N9qo8uLOi...)。关键在于这个过程是不可逆的:你无法从这串乱码还原出原始密码。
当用户下次登录时,系统不是去比对密码本身,而是把用户输入的密码再次通过同一台"绞肉机",然后比对两次产出的结果是否一致。这样,即使数据库被偷走,攻击者拿到的也只是一堆无法还原的乱码,而不是真正的密码。
为什么 AI 有时候不会主动帮你做这一步?因为明文存储在功能上完全"能跑"——用户能注册、能登录,一切表面正常。哈希处理是一个安全需求,而不是功能需求。如果你不主动要求,AI 可能会选择最简单的实现方式,而最简单的方式往往也是最危险的。
怎么避免重蹈覆辙
凡是涉及用户密码的存储,在要求 AI 实现时,明确说出"密码必须经过哈希处理后再存储"。 这一句话就够了。
验收时,你可以做一个简单的检查:去数据库里看一眼用户表。如果你能在密码字段里读出任何一个看起来像人类会输入的文字,那就说明密码没有被正确处理。正确哈希后的密码应该是一串你完全看不懂的长字符串。
如果你使用的是 Supabase 或 Firebase 这类后端即服务平台,它们内置的用户认证系统已经帮你处理好了密码哈希——这也是使用成熟平台的好处之一。但如果你让 AI 从头写一套登录系统,密码安全就是你必须主动关心的事情。
如何预防