UserDetails

UserDetailsUserDetailsService 返回。`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 实现中符合安全最佳实践,通过最小化敏感数据在内存中的生命周期,减少潜在的数据泄露风险。