密码哈希
bcrypt、scrypt、SHA;加盐存储。
30 分钟
密码哈希
数据库泄露时,明文或可逆加密 的密码会直接变成用户在其他网站的复用密码。密码哈希 的目标是:服务器只存 不可逆的指纹,登录时对用户输入做同样运算再比对。后端必须会用 慢哈希 + 唯一盐,并明白 SHA-256 单独用于密码 为什么不够。
学习目标
- 区分 哈希、加盐、 pepper、加密
- 选用 bcrypt / scrypt / Argon2 等密码专用算法
- 在 Spring 栈对接
PasswordEncoder,避免自造 crypto
不要做什么
| 做法 | 问题 |
|---|---|
| 明文存储 | 泄露即完蛋 |
| MD5 / SHA-256 无盐快哈希 | GPU 彩虹表秒破 |
| 自己设计「先 MD5 再 SHA1」 | 非专家极易出错 |
| 同一盐全库共用 | 削弱防护 |
| 可逆 AES 存密码 | 密钥泄露 = 全部密码还原 |
密码验证是单向的——忘记密码应 重置,不应「解密发邮件」。
盐(Salt)与 Pepper
- Salt:每用户随机,与哈希 一起存 DB;防彩虹表、同密码不同摘要
- Pepper:全站秘密,放 环境变量 / HSM,不进 DB;泄露 DB 仍缺 pepper
stored = bcrypt(password + pepper, salt) // pepper 可选,bcrypt 内置 salt 处理
Spring Security 的 BCryptPasswordEncoder 已把 salt 编进 $2a$10$... 字符串。
算法选型
| 算法 | 特点 | Spring 支持 |
|---|---|---|
| bcrypt | 成熟、自适应 cost | BCryptPasswordEncoder ✅ 默认推荐 |
| scrypt | 内存硬,抗 ASIC | 需额外库 |
| Argon2 | 现代 winner | Argon2PasswordEncoder(Spring 5+) |
| PBKDF2 | 标准、可调迭代 | Pbkdf2PasswordEncoder |
cost / iterations 要随硬件升级调高——不是配一次 forever。
Spring Boot 示例
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // strength 10–12 常见
}
// 注册
user.setPasswordHash(passwordEncoder.encode(rawPassword));
// 登录
if (!passwordEncoder.matches(rawPassword, user.getPasswordHash())) {
throw new BadCredentialsException("...");
}