AI 时代下的 Spring Security:为什么你的密码需要 `{bcrypt}` 前缀?
·
AI 时代下的 Spring Security:为什么你的密码需要 {bcrypt} 前缀?
引言:从“能跑”到“安全”
背景:AI 能帮你写
BCryptPasswordEncoder,但它不会告诉你为什么旧系统升级会挂掉。痛点:初创项目给个人使用时习惯直接明文密码,但是项目升级后安全领域也要进行相应的提升,而哈希值的保密程度在强大算力上有局限,现代主要采用自适应加密
核心机制:DelegatingPasswordEncoder (调度员模式)
主要流程
函数 验证密码(用户输入密码, 数据库存储的密码字符串):
1. 检查 数据库密码字符串 是否以 "{id}" 开头
2. 如果 没有前缀:
抛出错误 "找不到加密器 ID"
3. 提取 id (例如 "bcrypt")
4. 从地图中找到对应的 加密器 (例如 BCryptPasswordEncoder)
5. 使用找到的加密器 对比 (用户输入密码, 数据库密码字符串)
6. 返回 对比结果 (true/false)
根据密码字符串开头的
{id}标签,决定把任务派给哪个具体的加密器。
密码格式:{id}encodedPassword
WHY:为什么这样设计
- 平滑迁移:为了解决SpringSecurity5.0前后新旧密码共存的问题。
- 未来proof:可自定义适配未来新型的加密器
HOW:如何正确配置
场景一:Spring Boot 默认(99% 的情况)
官方文档中提到SpringBoot已经默认配置好DelegatingPasswordEncoder
场景二:测试与演示
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("user")
.build();
System.out.println(user.getPassword());
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
如需要创建多个用户,可以重复使用Builder,但是生产环境一定不要使用硬编码
场景三:遗留系统迁移
如果需要支持旧系统的明文或者 SHA-256,SpringSecurity引入DelegatingPasswordEncoder解决问题,根据特定的加密器自定义Map结合
登录情景
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
// 新默认算法
encoders.put("bcrypt", new BCryptPasswordEncoder());
// 兼容旧系统明文 (迁移专用,用完即删)
encoders.put("noop", NoOpPasswordEncoder.getInstance());
// 兼容旧系统 SHA-256
encoders.put("sha256", new StandardPasswordEncoder());
// 关键点:第一个参数 "bcrypt" 表示新注册用户默认用这个
return new DelegatingPasswordEncoder("bcrypt", encoders);
}
**常见陷阱与解决方案 **
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233)
at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196)
报错:There is no PasswordEncoder mapped for the id "null"
原因:数据库里的密码缺少 {bcrypt} 前缀。
解法:批量更新数据库加上前缀
UPDATE users SET password = CONCAT('{bcrypt}', password) WHERE password NOT LIKE '{%}';
性能调优:
- BCrypt 的
strength参数选多少?(建议:以登录耗时 ~0.5s-1s 为基准,通常 10-12,服务器强可更高)。
** 算法选型指南 **
- BCrypt: 默认推荐,兼容性好,足够安全。
- Argon2: 更现代,抗 GPU/ASIC 攻击能力更强,适合高安全需求场景(但需注意依赖库兼容性)。
- PBKDF2: 老旧系统常用,FIPS 合规场景可能需要。
如果需要使用默认加密器以外的加密器,需要自己在pom文件中引入依赖
总结
AI 负责生成样板代码。你还是要负责:
- 确认使用了
DelegatingPasswordEncoder。 - 检查数据库中是否有正确的
{id}前缀。 - 根据服务器性能调整加密强度。
- 制定密码迁移策略。
选到与项目最适配的方案
更多推荐


所有评论(0)