1. DelegatingPasswordEncoder 如何识别旧哈希并在登录后升级,升级写回失败是否应阻断认证
请说明 DelegatingPasswordEncoder 如何识别旧哈希并在登录后升级密码哈希,以及升级写回失败时是否应阻断认证?
- DelegatingPasswordEncoder 的编码前缀机制
- 登录后升级哈希的流程
- 写回失败的容错处理
DelegatingPasswordEncoder 支持同时管理多种密码编码器,通过编码前缀(如 {bcrypt}、{sha256}、{noop})识别存储的哈希属于哪种算法,从而在密码升级迁移期间兼容新旧哈希。它默认的"编码器 ID 前缀"机制:存储的哈希以 {id} 开头,matches 时根据前缀选择合适的编码器校验;encode 时统一使用默认编码器(如 bcrypt)并加上前缀。登录后升级流程:当用户登录成功时,若检测到存储的哈希前缀不是当前默认算法(如 {sha256}),则用新默认算法重新编码明文密码并写回数据库,实现无感升级。关于写回失败是否阻断认证:不应阻断——认证是否成功应完全取决于 matches 的校验结果,密码升级是"尽力而为"的辅助操作,写回失败(如数据库异常)不应导致已通过认证的用户登录失败,否则会造成可用性事故。正确处理是:先认证成功,再尝试升级写回,写回失败仅记日志、不影响认证结果。可参考 Spring Security 文档中 DaoAuthenticationProvider 的 upgradeEncoding 逻辑与 UserDetailsPasswordService。
本题考察 DelegatingPasswordEncoder 的升级机制与容错。核心是"前缀识别算法 + 登录后升级"与"写回失败不阻断认证"。回答应点出认证与升级解耦。