缓存 UserDetails
Spring Security 提供对使用 CachingUserDetailsService
缓存 UserDetails
的支持。或者,您可以使用 Spring Framework 的 @Cacheable
注解。在这两种情况下,您都需要 禁用凭据擦除 才能验证从缓存中检索到的密码。
CachingUserDetailsService
Spring Security 的 CachingUserDetailsService
实现 UserDetailsService 以提供对缓存 UserDetails
的支持。CachingUserDetailsService
通过委托给提供的 UserDetailsService
来提供对 UserDetails
的缓存支持。然后将结果存储在 UserCache
中,以减少后续调用的计算量。
以下示例仅定义一个 @Bean
,它封装了 UserDetailsService
的具体实现和用于缓存 UserDetails
的 UserCache
。
CachingUserDetailsService
@Bean
-
Java
-
Kotlin
@Bean
public CachingUserDetailsService cachingUserDetailsService(UserCache userCache) {
UserDetailsService delegate = ...;
CachingUserDetailsService service = new CachingUserDetailsService(delegate);
service.setUserCache(userCache);
return service;
}
@Bean
fun cachingUserDetailsService(userCache: UserCache): CachingUserDetailsService {
val delegate: UserDetailsService = ...
val service = CachingUserDetailsService(delegate)
service.userCache = userCache
return service
}
@Cacheable
另一种方法是使用 Spring 框架的 @Cacheable
在您的 UserDetailsService
实现中,通过 username
缓存 UserDetails
。这种方法的优点是配置更简单,尤其是在您已经在应用程序的其他地方使用缓存的情况下。
以下示例假设缓存已配置,并使用 @Cacheable
注释 loadUserByUsername
@Cacheable
注释的 UserDetailsService
-
Java
-
Kotlin
@Service
public class MyCustomUserDetailsImplementation implements UserDetailsService {
@Override
@Cacheable
public UserDetails loadUserByUsername(String username) {
// some logic here to get the actual user details
return userDetails;
}
}
@Service
class MyCustomUserDetailsImplementation : UserDetailsService {
@Cacheable
override fun loadUserByUsername(username: String): UserDetails {
// some logic here to get the actual user details
return userDetails
}
}
禁用凭据擦除
无论您使用 CachingUserDetailsService
还是 @Cacheable
,您都需要禁用 凭据擦除,以便 UserDetails
包含一个 password
,以便在从缓存中检索时进行验证。以下示例通过配置 Spring Security 提供的 AuthenticationManagerBuilder
,为全局 AuthenticationManager
禁用凭据擦除
AuthenticationManager
禁用凭据擦除-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// ...
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
// Return a UserDetailsService that caches users
// ...
}
@Autowired
public void configure(AuthenticationManagerBuilder builder) {
builder.eraseCredentials(false);
}
}
import org.springframework.security.config.annotation.web.invoke
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
// ...
return http.build()
}
@Bean
fun userDetailsService(): UserDetailsService {
// Return a UserDetailsService that caches users
// ...
}
@Autowired
fun configure(builder: AuthenticationManagerBuilder) {
builder.eraseCredentials(false)
}
}