| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 | [[servlet-authentication-caching-user-details]]= Caching `UserDetails`Spring Security provides support for caching `UserDetails` with <<servlet-authentication-caching-user-details-service,`CachingUserDetailsService`>>.Alternatively, you can use Spring Framework's <<servlet-authentication-caching-user-details-cacheable,`@Cacheable`>> annotation.In either case, you will need to <<servlet-authentication-caching-user-details-credential-erasure,disable credential erasure>> 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"]----@Beanpublic CachingUserDetailsService cachingUserDetailsService(UserCache userCache) {	UserDetailsService delegate = ...;    CachingUserDetailsService service = new CachingUserDetailsService(delegate);    service.setUserCache(userCache);    return service;}----Kotlin::+[source,kotlin,role="secondary"]----@Beanfun 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"]----@Servicepublic 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"]----@Serviceclass 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 ErasureWhether you use <<servlet-authentication-caching-user-details-service,`CachingUserDetailsService`>> or <<servlet-authentication-caching-user-details-cacheable,`@Cacheable`>>, 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@EnableWebSecuritypublic 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@EnableWebSecurityclass 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)	}}----=====
 |