必须在应用层使用bcrypt/Argon2等带随机盐和迭代的慢哈希算法,因MySQL内置MD5()、SHA2()无随机盐且计算过快,易遭彩虹表和暴力破解;caching_sha2_password仅用于连接认证,不适用于业务密码存储。

必须在应用层加盐哈希,MySQL内置函数无法满足现代安全要求
为什么不能用 MD5() 或 SHA2() 直接存密码
这些函数是确定性单向哈希:相同输入永远输出相同结果。攻击者拿到 authentication_string 后,可直接查彩虹表或跑字典——尤其对弱口令(如 '123456'、'password')几乎秒破。即使加固定盐(如 CONCAT('mysalt', password)),所有用户共用同一盐值,仍无法抵御批量碰撞。
- MySQL 的
MD5()、SHA2(password, 256)不带随机盐,也不做密钥派生迭代 -
mysql_native_password插件虽用双 SHA-1,但无盐且算法已过时,2026 年已被主流工具弃用 -
caching_sha2_password虽在认证时用随机盐 + SHA-256,但它只用于连接认证,不暴露哈希值,且mysql.user表中存储的哈希不可逆用于业务密码校验
应用层必须用 bcrypt / Argon2 / PBKDF2
这些算法天然带随机盐 + 可调迭代次数,让哈希计算变慢、不可并行,极大提高暴力破解成本。MySQL 本身不提供这类函数,必须由应用完成。
- PHP:用
password_hash($pwd, PASSWORD_ARGON2ID),验证用password_verify() - Python:用
passlib.hash.bcrypt或hashlib.scrypt(需 Python ≥ 3.6) - Java:用
BCryptPasswordEncoder(Spring Security)或SecretKeyFactory(PBKDF2) - 存储字段类型建议为
VARCHAR(255),因为 bcrypt 输出含盐和参数(如$2y$10$...),长度可变
数据库层面配合加固,防止哈希值被拖库后直接利用
即使哈希本身安全,若攻击者拿到整个 users 表,仍可能离线爆破弱口令。必须叠加防御纵深:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 对
password_hash字段启用透明数据加密(TDE)或使用AES_ENCRYPT()加密存储(但注意密钥管理风险) - 限制数据库账号权限:业务账号仅能
SELECT必要字段,禁止SELECT * FROM users或导出全表 - 开启审计日志(
mysql.enterprise_audit),监控异常查询行为,如高频访问password_hash字段 - 连接必须走 TLS:防止中间人截获登录请求中的明文密码(哪怕只是临时传输)
最容易被忽略的点:盐不是“加个字符串”就完事
很多开发者误以为 MD5(CONCAT('abc123', password)) 就算加盐了——这是伪安全。真正的盐必须:
- 每用户唯一(用
random_bytes(16)生成,Base64 编码后存入字段salt) - 长度足够(≥ 16 字节),且与哈希值一同存储(bcrypt 等已内置,无需单独字段)
- 绝不复用、绝不硬编码、绝不从配置文件读取全局盐
否则,一旦盐泄露,所有用户哈希等同于裸奔。而 bcrypt 的 salt 已随哈希字符串一起生成和存储,这才是正确姿势。










