Caching UserDetails

Spring Security 提供使用 <<`CachingUserDetailsService`,servlet-authentication-caching-user-details-service>> 缓存 UserDetails 的支持。或者,你可以使用 Spring 框架的 <<`@Cacheable`,servlet-authentication-caching-user-details-cacheable>> 注解。在任何情况下,你都需要 disable credential erasure 以便验证从缓存中检索到的密码。

Spring Security provides support for caching UserDetails with <<`CachingUserDetailsService`,servlet-authentication-caching-user-details-service>>. Alternatively, you can use Spring Framework’s <<`@Cacheable`,servlet-authentication-caching-user-details-cacheable>> annotation. In either case, you will need to servlet-authentication-caching-user-details-credential-erasure in order to validate passwords retrieved from the cache.

CachingUserDetailsService

Spring Security 的 CachingUserDetailsService 会实现 UserDetailsService,以提供缓存 UserDetails 的支持。CachingUserDetailsService 通过委托到提供的 UserDetailsService 来为 UserDetails 提供缓存支持。然后将结果存储在 UserCache 中,以减少后续调用中的计算。

Spring Security’s CachingUserDetailsService implements UserDetailsService to provide support for caching UserDetails. CachingUserDetailsService provides caching support for UserDetails by delegating to the provided UserDetailsService. The result is then stored in a UserCache to reduce computation in subsequent calls.

以下示例简单地定义了一个 @Bean,该 @Bean 封装了 UserDetailsService 和一个用于缓存 UserDetailsUserCache 的具体实现:

The following example simply defines a @Bean that encapsulates a concrete implementation of UserDetailsService and a UserCache for caching the UserDetails:

Provide a 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 Framework 的{spring-framework-reference-url}integration.html#cache-annotations-cacheable[@Cacheable] 在您的`UserDetailsService`实现中按`username`缓存`UserDetails`。这种方法的好处是配置更简单,尤其是当您已经在应用程序中的其他位置使用缓存时。

An alternative approach would be to use Spring Framework’s {spring-framework-reference-url}integration.html#cache-annotations-cacheable[@Cacheable] in your UserDetailsService implementation to cache UserDetails by username. The benefit to this approach is simpler configuration, especially if you are already using caching elsewhere in your application.

以下示例假定已配置缓存,并通过 @CacheableloadUserByUsername 提供注释:

The following example assumes caching is already configured, and annotates the loadUserByUsername with @Cacheable:

UserDetailsService annotated with @Cacheable
  • 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
    }
}

Disable Credential Erasure

无论您使用 <<`CachingUserDetailsService`,servlet-authentication-caching-user-details-service>> 或 <<`@Cacheable`,servlet-authentication-caching-user-details-cacheable>>, 您都需要禁用 credential erasure,以便 UserDetails 包含将从缓存中检索时验证的 password。以下示例通过配置 Spring Security 提供的 AuthenticationManagerBuilder,禁用全局 AuthenticationManager 的证书删除:

Whether you use <<`CachingUserDetailsService`,servlet-authentication-caching-user-details-service>> or <<`@Cacheable`,servlet-authentication-caching-user-details-cacheable>>, you will need to disable credential erasure so that the UserDetails will contain a password to be validated when retrieved from the cache. The following example disables credential erasure for the global AuthenticationManager by configuring the AuthenticationManagerBuilder provided by Spring Security:

Disable credential erasure for the global 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)
	}

}