UserDetails のキャッシング

Spring Security は、CachingUserDetailsService を使用した UserDetails のキャッシュのサポートを提供します。あるいは、Spring Framework の @Cacheable アノテーションを使用することもできます。どちらの場合も、キャッシュから取得したパスワードを検証するには、資格情報の消去を無効にする必要があります。

CachingUserDetailsService

Spring Security の CachingUserDetailsService は UserDetailsService を実装して、UserDetails のキャッシュのサポートを提供します。CachingUserDetailsService は、提供された UserDetailsService に委譲することで、UserDetails のキャッシュサポートを提供します。その後、結果は UserCache に保存され、後続の呼び出しでの計算が軽減されます。

次の例では、UserDetailsService の具体的な実装をカプセル化する @Bean と、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

別のアプローチは、UserDetailsService 実装で Spring Framework の @Cacheable を使用して、username によって UserDetails をキャッシュすることです。このアプローチの利点は、特にアプリケーションの他の場所でキャッシュをすでに使用している場合に、構成が簡単になることです。

次の例では、キャッシュがすでに構成されており、loadUserByUsername に @Cacheable のアノテーションが付けられていることを前提としています。

 @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 のどちらを使用する場合でも、キャッシュから取得するときに検証される password が UserDetails に含まれるように、資格情報の消去を無効にする必要があります。次の例では、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)
	}

}