用户详情
UserDetails 由 UserDetailsService 返回。DaoAuthenticationProvider 验证 UserDetails
,然后返回一个 Authentication,其主体是配置的 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
}
}
实施指南
-
立即擦除:凭证应在不再需要时立即擦除,通常是在身份验证后。
-
自动调用:确保
eraseCredentials()
在身份验证过程完成后由你的身份验证框架(如AuthenticationManager
)自动调用。 -
一致性:在所有应用程序中统一应用此做法,以防止可能导致数据泄露的安全疏漏。
超出基本接口实现
虽然像 CredentialsContainer
这样的接口为凭证管理提供了一个框架,但实际实现通常依赖于特定的类及其交互。
例如,DaoAuthenticationProvider
类遵循 AuthenticationProvider
的契约,在其自身的 authenticate
方法中不执行凭证擦除。相反,它依赖于 ProviderManager
(Spring Security 的 AuthenticationManager
默认实现)在认证后处理凭证和其他敏感数据的擦除。这种分离强调了 AuthenticationProvider
不应承担凭证管理责任的原则。
将 CredentialsContainer
纳入你的 UserDetails
实现符合安全最佳实践,通过减少内存中敏感数据的生命周期来降低数据泄露的潜在风险。