[[servlet-authentication-caching-user-details]] = Caching `UserDetails` Spring Security provides support for caching `UserDetails` with <>. Alternatively, you can use Spring Framework's <> annotation. In either case, you will need to <> in order to validate passwords retrieved from the cache. [[servlet-authentication-caching-user-details-service]] == `CachingUserDetailsService` Spring Security's `CachingUserDetailsService` implements xref:servlet/authentication/passwords/user-details-service.adoc#servlet-authentication-userdetailsservice[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. 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` [tabs] ====== Java:: + [source,java,role="primary"] ---- @Bean public CachingUserDetailsService cachingUserDetailsService(UserCache userCache) { UserDetailsService delegate = ...; CachingUserDetailsService service = new CachingUserDetailsService(delegate); service.setUserCache(userCache); return service; } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- @Bean fun cachingUserDetailsService(userCache: UserCache): CachingUserDetailsService { val delegate: UserDetailsService = ... val service = CachingUserDetailsService(delegate) service.userCache = userCache return service } ---- ====== [[servlet-authentication-caching-user-details-cacheable]] == `@Cacheable` 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. The following example assumes caching is already configured, and annotates the `loadUserByUsername` with `@Cacheable`: .`UserDetailsService` annotated with `@Cacheable` [tabs] ====== Java:: + [source,java,role="primary"] ---- @Service public class MyCustomUserDetailsImplementation implements UserDetailsService { @Override @Cacheable public UserDetails loadUserByUsername(String username) { // some logic here to get the actual user details return userDetails; } } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- @Service class MyCustomUserDetailsImplementation : UserDetailsService { @Cacheable override fun loadUserByUsername(username: String): UserDetails { // some logic here to get the actual user details return userDetails } } ---- ====== [[servlet-authentication-caching-user-details-credential-erasure]] == Disable Credential Erasure Whether you use <> or <>, you will need to disable xref:servlet/authentication/architecture.adoc#servlet-authentication-providermanager-erasing-credentials[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` [tabs] ===== Java:: + [source,java,role="primary"] ---- @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); } } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- 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) } } ---- =====