用户详情
UserDetails 由 UserDetailsService 返回。DaoAuthenticationProvider 会验证 UserDetails,然后返回一个 Authentication,其主体(principal)就是配置的 UserDetailsService 所返回的 UserDetails。
凭证管理
强烈建议在存储用户凭据的类中实现 CredentialsContainer 接口,例如那些扩展或实现 UserDetails 的类,尤其是在不缓存用户详细信息的应用程序中。这种做法通过确保敏感数据(如密码)不会在内存中保留超过必要的时间,从而增强了安全性。
在缓存用户详情的情况下,考虑创建一个不包含凭据的 UserDetails 副本,并在自定义 AuthenticationProvider 的响应中返回该副本,而不是原始对象。这有助于防止认证过程完成后,应用程序的其他部分引用包含凭据的缓存实例。
何时实现 CredentialsContainer
未采用缓存机制存储UserDetails的应用程序应特别考虑实现CredentialsContainer接口。这种方法有助于降低敏感信息保留在内存中的风险,此类信息可能容易受到内存转储等攻击向量的威胁。
public class MyUserDetails implements UserDetails, CredentialsContainer {
private String username;
private String password;
// UserDetails implementation...
@Override
public void eraseCredentials() {
this.password = null; // Securely dereference the password field
}
}
实现指南
-
即时擦除:凭证应在不再需要时立即擦除,通常是在身份验证之后。
-
自动调用:确保身份验证框架(例如
AuthenticationManager)在身份验证过程完成后自动调用eraseCredentials()方法。 -
一致性:在所有应用程序中统一应用此实践,以防止可能导致数据泄露的安全漏洞。
超越基础接口实现
虽然像 CredentialsContainer 这样的接口为凭证管理提供了框架,但实际实现通常依赖于具体的类及其交互。
例如,DaoAuthenticationProvider类遵循AuthenticationProvider的契约,并未在其自身的authenticate方法中执行凭证擦除。相反,它依赖于ProviderManager——Spring Security默认的AuthenticationManager实现——来处理认证后凭证及其他敏感数据的擦除。这种分离强调了AuthenticationProvider不应承担凭证管理责任的原则。
将 CredentialsContainer 集成到您的 UserDetails 实现中符合安全最佳实践,通过减少敏感数据在内存中的存留时间来降低潜在的数据泄露风险。