Spring WebFlux で InMemoryWebSessionStore にセッションタイムアウトを設定する

概要

Spring WebFlux を使いながら application.properties で spring.session.timeout を設定した際、設定が効きませんでした。WebFlux の WebSessionStore をカスタマイズして、セッションタイムアウトの間隔を設定する方法を説明します。

目次

確認環境

  • Spring Boot 2.0.3.RELEASE
  • Kotlin 1.2.50

参考情報

解説

設定方法

以下の示す様に WebSessionManager に設定する WebSessionStore を変更します。

@EnableWebFluxSecurity
@EnableConfigurationProperties(SessionProperties::class)
@Configuration
class ExampleConfig {
    // ...

    @Bean
    fun webSessionManager(properties: SessionProperties): WebSessionManager {
        return DefaultWebSessionManager().apply {
            sessionIdResolver = HeaderWebSessionIdResolver().apply {
                headerName = "X-Sample" // セッションIDのヘッダー名を変更する場合には設定
            }
            sessionStore = CustomizableInMemoryWebSessionStore(properties)
        }
    }
}

WebSessionManager としては DefaultWebSessionManager を使います。DefaultWebSessionManager では、WebSessionIdResolver と WebSessionStore を指定します。デフォルトは、CookieWebSessionIdResolverInMemoryWebSessionStore です。

セッションタイムアウトには、WebSessionStore が関係しています。WebSessionStore がセッションの生成と破棄を行っています。デフォルトの InMemoryWebSessionStore では、InMemoryWebSession オブジェクトの maxIdleTime で有効期間の判定を行っています。デフォルトの maxIdleTime は 30 分になっています。

WebSessionStore に application.properties の設定内容を渡すために、EnableConfigurationProperties を使って SessionProperties を Bean として設定しています。これにより、webSessionManager メソッドの引数で SessionProperties Bean を注入できる様になります。SessionProperties は application.properties のうち、spring.session に含まれる設定内容を保持しています。InMemoryWebSessionStore 自体は SessionProperties を受け取らないため、InMemoryWebSessionStore を拡張したクラスのオブジェクトを使います。

本筋からは逸れますが、WebSessionIdResolver はリクエストとレスポンスにおいてセッションIDの取得と設定を行う処理を持ちます。HeaderWebSessionIdResolver を使えば、セッションIDを設定するヘッダーを変更できます。上記の例では、X-Sample ヘッダーにセッションIDを設定させています。

次に、InMemoryWebSessionStore を拡張した CustomizableInMemoryWebSessionStore です。

class CustomizableInMemoryWebSessionStore(
        private val properties: SessionProperties
) : InMemoryWebSessionStore() {

    override fun createWebSession(): Mono<WebSession> = super
            .createWebSession()
            .map(this::applySessionProperties)

    private fun applySessionProperties(session: WebSession) = session.apply {
        maxIdleTime = properties.timeout
    }
}

WebSession オブジェクトを生成する際に、maxIdleTime を application.properties の spring.session.timeout の値に変更しています。