認証の永続性とセッション管理

リクエストを認証するアプリケーションを取得したら、その結果の認証をどのように保持し、将来のリクエストで復元するかを検討することが重要です。

これはデフォルトで自動的に行われるため、追加のコードは必要ありませんが、HttpSecurity で requireExplicitSave が何を意味するかを知ることは重要です。

必要に応じて、requireExplicitSave の機能重要性について詳しく読むことができます。それ以外の場合は、ほとんどの場合、このセクションで完了です。

ただし、終了する前に、次のユースケースのいずれかがアプリケーションに適合するかどうかを検討してください。

セッション管理のコンポーネントを理解する

セッション管理サポートは、連携して機能を提供するいくつかのコンポーネントで構成されています。これらのコンポーネントは、SecurityContextHolderFilterSecurityContextPersistenceFilter、および SessionManagementFilter です。

Spring Security 6 では、SecurityContextPersistenceFilter と SessionManagementFilter はデフォルトでは設定されていません。それに加えて、どのアプリケーションでも SecurityContextHolderFilter または SecurityContextPersistenceFilter のいずれかのみを設定する必要があり、両方を設定することはできません。

SessionManagementFilter

SessionManagementFilter は、SecurityContextRepository のコンテンツを SecurityContextHolder の現在のコンテンツと照合して、通常、事前認証や remember-me [ 1 ] などの非対話型認証メカニズムによって現在のリクエスト中にユーザーが認証されたかどうかを判断します。リポジトリにセキュリティコンテキストが含まれている場合、フィルターは何もしません。存在せず、スレッドローカル SecurityContext に(非匿名の) Authentication オブジェクトが含まれている場合、フィルターは、スタック内の前のフィルターによって認証されたと見なします。次に、構成された SessionAuthenticationStrategy を呼び出します。

ユーザーが現在認証されていない場合、フィルターは無効なセッション ID がリクエストされているかどうかを確認し(タイムアウトなどが原因)、設定されている InvalidSessionStrategy が設定されている場合はそれを呼び出します。最も一般的な動作は、固定 URL にリダイレクトすることであり、これは標準実装 SimpleRedirectInvalidSessionStrategy にカプセル化されています。後者は、前述のように、名前空間を介して無効なセッション URL を構成するときにも使用されます。

SessionManagementFilter からの脱却

Spring Security 5 では、デフォルト構成は SessionManagementFilter に依存して、ユーザーが認証されたかどうかを検出し、SessionAuthenticationStrategy (Javadoc) を呼び出します。これの問題は、典型的なセットアップでは、リクエストごとに HttpSession を読み取らなければならないことを意味することです。

Spring Security 6 では、デフォルトでは、認証メカニズム自体が SessionAuthenticationStrategy を呼び出す必要があります。つまり、Authentication がいつ完了したかを検出する必要がないため、リクエストごとに HttpSession を読み取る必要はありません。

SessionManagementFilter から離れる際の注意点

Spring Security 6 では、SessionManagementFilter はデフォルトで使用されないため、sessionManagement DSL の一部のメソッドは効果がありません。

メソッド 置換文字列

sessionAuthenticationErrorUrl

認証メカニズムで AuthenticationFailureHandler (Javadoc) を構成する

sessionAuthenticationFailureHandler

認証メカニズムで AuthenticationFailureHandler (Javadoc) を構成する

sessionAuthenticationStrategy

上記で説明したように、認証メカニズムで SessionAuthenticationStrategy を構成します。

これらのメソッドのいずれかを使用しようとすると、例外がスローされます。

認証の保存場所のカスタマイズ

デフォルトでは、Spring Security はセキュリティコンテキストを HTTP セッションに保存します。ただし、これをカスタマイズする理由がいくつかあります。

  • HttpSessionSecurityContextRepository インスタンスで個々の setter を呼び出すこともできます

  • セキュリティコンテキストをキャッシュまたはデータベースに格納して、水平方向のスケーリングを有効にすることができます。

まず、SecurityContextRepository の実装を作成するか、HttpSessionSecurityContextRepository などの既存の実装を使用する必要があります。次に、それを HttpSecurity に設定できます。

SecurityContextRepository のカスタマイズ
  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    SecurityContextRepository repo = new MyCustomSecurityContextRepository();
    http
        // ...
        .securityContext((context) -> context
            .securityContextRepository(repo)
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    val repo = MyCustomSecurityContextRepository()
    http {
        // ...
        securityContext {
            securityContextRepository = repo
        }
    }
    return http.build()
}
<http security-context-repository-ref="repo">
    <!-- ... -->
</http>
<bean name="repo" class="com.example.MyCustomSecurityContextRepository" />

上記の構成では、SecurityContextHolderFilter に SecurityContextRepository を設定し、参加する認証フィルター ( UsernamePasswordAuthenticationFilter など) を設定します。ステートレスフィルターにも設定するには、ステートレス認証用に SecurityContextRepository をカスタマイズする方法を参照してください。

カスタム認証メカニズムを使用している場合は、自分で Authentication を保存することをお勧めします。

Authentication を手動で保管する

たとえば、場合によっては、Spring Security フィルターに頼るのではなく、手動でユーザーを認証することがあります。これを行うには、カスタムフィルターまたは Spring MVC コントローラーエンドポイントを使用できます。たとえば、リクエスト間の認証を HttpSession に保存する場合は、次のようにする必要があります。

  • Java

private SecurityContextRepository securityContextRepository =
        new HttpSessionSecurityContextRepository(); (1)

@PostMapping("/login")
public void login(@RequestBody LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) { (2)
    UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated(
        loginRequest.getUsername(), loginRequest.getPassword()); (3)
    Authentication authentication = authenticationManager.authenticate(token); (4)
    SecurityContext context = securityContextHolderStrategy.createEmptyContext();
    context.setAuthentication(authentication); (5)
    securityContextHolderStrategy.setContext(context);
    securityContextRepository.saveContext(context, request, response); (6)
}

class LoginRequest {

    private String username;
    private String password;

    // getters and setters
}
1 コントローラーに SecurityContextRepository を追加
2HttpServletRequest と HttpServletResponse を注入して、SecurityContext を保存できるようにします。
3 提供された資格情報を使用して、認証されていない UsernamePasswordAuthenticationToken を作成します
4AuthenticationManager#authenticate を呼び出してユーザーを認証する
5SecurityContext を作成し、その中に Authentication を設定します
6SecurityContext を SecurityContextRepository に保存します

以上です。上記の例で securityContextHolderStrategy が何であるかわからない場合は、SecurityContextStrategy セクションの使用で詳細を読むことができます。

認証を適切にクリアする

Spring Security のログアウトのサポートを使用している場合は、コンテキストのクリアや保存など、多くのことを処理します。ただし、ユーザーをアプリから手動でログアウトする必要があるとします。その場合、コンテキストを適切にクリアして保存していることを確認する必要があります。

ステートレス認証の永続性の構成

たとえば、リクエスト間で認証を永続化するために、HttpSession を作成して維持する必要がない場合があります。HTTP ベーシックなどの一部の認証メカニズムはステートレスであるため、リクエストごとにユーザーを再認証します。

セッションを作成したくない場合は、次のように SessionCreationPolicy.STATELESS を使用できます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        // ...
        .sessionManagement((session) -> session
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        // ...
        sessionManagement {
            sessionCreationPolicy = SessionCreationPolicy.STATELESS
        }
    }
    return http.build()
}
<http create-session="stateless">
    <!-- ... -->
</http>

SessionCreationPolicy.NEVER を使用している場合、アプリケーションがまだ HttpSession を作成していることに気付くかもしれません。ほとんどの場合、これは、認証が成功した後に認証されたリソースが再リクエストするために、リクエストがセッションに保存されるために発生します。これを回避するには、セクションの保存リクエストを防止する方法を参照してください。

セッションへのステートレス認証の保存

何らかの理由で、ステートレス認証メカニズムを使用しているが、認証をセッションに保存したい場合は、NullSecurityContextRepository の代わりに HttpSessionSecurityContextRepository を使用できます。

HTTP ベーシックの場合、BasicAuthenticationFilter で使用される SecurityContextRepository を変更する ObjectPostProcessor を追加できます。

HttpSession に HTTP 基本認証を格納します
  • Java

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        // ...
        .httpBasic((basic) -> basic
            .addObjectPostProcessor(new ObjectPostProcessor<BasicAuthenticationFilter>() {
                @Override
                public <O extends BasicAuthenticationFilter> O postProcess(O filter) {
                    filter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
                    return filter;
                }
            })
        );

    return http.build();
}

上記は、ベアラートークン認証などの他の認証メカニズムにも適用されます。

明示的な保存が必要であることを理解する

Spring Security 5 のデフォルトの動作は、SecurityContextPersistenceFilter を使用して SecurityContextSecurityContextRepository に自動的に保存されることです。保存は、HttpServletResponse がコミットされる直前、および SecurityContextPersistenceFilter の直前に行う必要があります。残念ながら、SecurityContext の自動永続化は、リクエストが完了する前 (つまり、HttpServletResponse をコミットする直前) に行われると、ユーザーを驚かせる可能性があります。また、状態を追跡して保存が必要かどうかを判断するのも複雑で、SecurityContextRepository (つまり HttpSession) への不必要な書き込みが発生することがあります。

これらの理由から、SecurityContextPersistenceFilter は廃止され、SecurityContextHolderFilter に置き換えられました。Spring Security 6 では、デフォルトの動作として、SecurityContextHolderFilter は SecurityContextRepository から SecurityContext のみを読み取り、それを SecurityContextHolder に入力します。リクエスト間で SecurityContext を維持したい場合、ユーザーは SecurityContextRepository で SecurityContext を明示的に保存する必要があります。これにより、必要なときにのみ SecurityContextRepository (つまり HttpSession) への書き込みが必要になるため、あいまいさがなくなり、パフォーマンスが向上します。

使い方

要約すると、requireExplicitSave が true の場合、Spring Security は SecurityContextPersistenceFilter の代わりに SecurityContextHolderFilter をセットアップします。

同時セッション制御の構成

1 人のユーザーがアプリケーションにログインする機能に制約を課したい場合、Spring Security は、次の簡単な追加で、これをすぐにサポートします。まず、セッションライフサイクルイベントについて Spring Security を最新の状態に保つために、構成に次のリスナーを追加する必要があります。

  • Java

  • Kotlin

  • web.xml

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}
@Bean
open fun httpSessionEventPublisher(): HttpSessionEventPublisher {
    return HttpSessionEventPublisher()
}
<listener>
<listener-class>
    org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>

次に、セキュリティ構成に次の行を追加します。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement(session -> session
            .maximumSessions(1)
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            sessionConcurrency {
                maximumSessions = 1
            }
        }
    }
    return http.build()
}
<http>
...
<session-management>
    <concurrency-control max-sessions="1" />
</session-management>
</http>

これにより、ユーザーが複数回ログインすることが防止されます。2 回目のログインにより、最初のログインが無効になります。

Spring Boot を使用すると、上記の構成シナリオを次の方法でテストできます。

  • Java

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class MaximumSessionsTests {

    @Autowired
    private MockMvc mvc;

    @Test
    void loginOnSecondLoginThenFirstSessionTerminated() throws Exception {
        MvcResult mvcResult = this.mvc.perform(formLogin())
                .andExpect(authenticated())
                .andReturn();

        MockHttpSession firstLoginSession = (MockHttpSession) mvcResult.getRequest().getSession();

        this.mvc.perform(get("/").session(firstLoginSession))
                .andExpect(authenticated());

        this.mvc.perform(formLogin()).andExpect(authenticated());

        // first session is terminated by second login
        this.mvc.perform(get("/").session(firstLoginSession))
                .andExpect(unauthenticated());
    }

}

最大セッション数のサンプル [GitHub] (英語) を使用して試すことができます。

また、2 回目のログインを防止したい場合もよくあります。その場合は、次を使用できます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement(session -> session
            .maximumSessions(1)
            .maxSessionsPreventsLogin(true)
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            sessionConcurrency {
                maximumSessions = 1
                maxSessionsPreventsLogin = true
            }
        }
    }
    return http.build()
}
<http>
<session-management>
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>

2 回目のログインは拒否されます。「拒否」とは、フォームベースのログインが使用されている場合、ユーザーが authentication-failure-url に送信されることを意味します。2 番目の認証が "remember-me" などの別の非対話型メカニズムを介して行われる場合、"unauthorized" (401) エラーがクライアントに送信されます。代わりにエラーページを使用する場合は、session-authentication-error-url 属性を session-management 要素に追加できます。

Spring Boot を使用すると、上記の構成を次の方法でテストできます。

  • Java

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class MaximumSessionsPreventLoginTests {

    @Autowired
    private MockMvc mvc;

    @Test
    void loginOnSecondLoginThenPreventLogin() throws Exception {
        MvcResult mvcResult = this.mvc.perform(formLogin())
                .andExpect(authenticated())
                .andReturn();

        MockHttpSession firstLoginSession = (MockHttpSession) mvcResult.getRequest().getSession();

        this.mvc.perform(get("/").session(firstLoginSession))
                .andExpect(authenticated());

        // second login is prevented
        this.mvc.perform(formLogin()).andExpect(unauthenticated());

        // first session is still valid
        this.mvc.perform(get("/").session(firstLoginSession))
                .andExpect(authenticated());
    }

}

フォームベースのログイン用にカスタマイズされた認証フィルターを使用している場合は、同時セッション制御のサポートを明示的に構成する必要があります。ログインを防止する最大セッション数のサンプル [GitHub] (英語) を使用して試すことができます。

タイムアウトの検出

セッションは自然に期限切れになり、セキュリティコンテキストが確実に削除されるようにするために必要なことは何もありません。とはいえ、Spring Security はセッションの有効期限が切れたことを検出し、指定された特定のアクションを実行できます。例: ユーザーがすでに期限切れのセッションでリクエストを行ったときに、特定のエンドポイントにリダイレクトしたい場合があります。これは、HttpSecurity の invalidSessionUrl によって実現されます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement(session -> session
            .invalidSessionUrl("/invalidSession")
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            invalidSessionUrl = "/invalidSession"
        }
    }
    return http.build()
}
<http>
...
<session-management invalid-session-url="/invalidSession" />
</http>

このメカニズムを使用してセッションタイムアウトを検出する場合、ユーザーがログアウトしてブラウザーを閉じずに再度ログインすると、誤ってエラーが報告される可能性があることに注意してください。これは、セッションを無効にしたときにセッション cookie がクリアされず、ユーザーがログアウトした場合でも再送信されるためです。その場合は、セッション Cookie をクリアするようにログアウトを構成することをお勧めします。

無効なセッション戦略のカスタマイズ

invalidSessionUrl は、SimpleRedirectInvalidSessionStrategy の実装 (Javadoc) を使用して InvalidSessionStrategy を設定する便利なメソッドです。動作をカスタマイズする場合は、InvalidSessionStrategy (Javadoc) インターフェースを実装し、invalidSessionStrategy メソッドを使用して構成できます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement(session -> session
            .invalidSessionStrategy(new MyCustomInvalidSessionStrategy())
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            invalidSessionStrategy = MyCustomInvalidSessionStrategy()
        }
    }
    return http.build()
}
<http>
...
<session-management invalid-session-strategy-ref="myCustomInvalidSessionStrategy" />
<bean name="myCustomInvalidSessionStrategy" class="com.example.MyCustomInvalidSessionStrategy" />
</http>

ログアウト時に JSESSIONID Cookie を明示的に削除できます。たとえば、ログアウトハンドラーで Clear-Site-Data ヘッダー (英語) を使用します。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .logout((logout) -> logout
            .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(COOKIES)))
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        logout {
            addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(COOKIES)))
        }
    }
    return http.build()
}
<http>
<logout success-handler-ref="clearSiteDataHandler" />
<b:bean id="clearSiteDataHandler" class="org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler">
    <b:constructor-arg>
        <b:bean class="org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter">
            <b:constructor-arg>
                <b:list>
                    <b:value>COOKIES</b:value>
                </b:list>
            </b:constructor-arg>
        </b:bean>
    </b:constructor-arg>
</b:bean>
</http>

これには、コンテナーに依存しないという利点があり、Clear-Site-Data ヘッダーをサポートするすべてのコンテナーで機能します。

別の方法として、ログアウトハンドラーで次の構文を使用することもできます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .logout(logout -> logout
            .deleteCookies("JSESSIONID")
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        logout {
            deleteCookies("JSESSIONID")
        }
    }
    return http.build()
}
<http>
  <logout delete-cookies="JSESSIONID" />
</http>

残念ながら、これがすべてのサーブレットコンテナーで機能することを保証できるわけではないため、ご使用の環境でテストする必要があります。

アプリケーションをプロキシの背後で実行している場合は、プロキシサーバーを構成することでセッション Cookie を削除できる場合もあります。例: Apache HTTPD の mod_headers を使用すると、次のディレクティブは、ログアウトリクエストへのレスポンスで期限切れにすることで JSESSIONID Cookie を削除します (アプリケーションが /tutorial パスにデプロイされていると仮定)。

<LocationMatch "/tutorial/logout">
Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT"
</LocationMatch>

セッション固定攻撃保護について

セッション固定 [Wikipedia] 攻撃は、悪意のある攻撃者がサイトにアクセスしてセッションを作成し、別のユーザーに同じセッションでログインするように仕向ける可能性のある潜在的なリスクです (たとえば、セッション ID をパラメーターとして含むリンクを送信することにより))。Spring Security は、新しいセッションを作成するか、ユーザーがログインするときにセッション ID を変更することによって、これを自動的に保護します。

セッション固定保護の構成

次の 3 つの推奨オプションから選択することで、セッション固定保護の戦略を制御できます。

  • changeSessionId - 新しいセッションを作成しないでください。代わりに、サーブレットコンテナー(HttpServletRequest#changeSessionId())によって提供されるセッション固定保護を使用します。このオプションは、Servlet 3.1(Java EE 7)以降のコンテナーでのみ使用可能です。古いコンテナーで指定すると、例外が発生します。これは、Servlet 3.1 以降のコンテナーのデフォルトです。

  • newSession - 既存のセッションデータをコピーせずに、新しい「クリーン」セッションを作成します(Spring セキュリティ関連の属性は引き続きコピーされます)。

  • migrateSession - 新しいセッションを作成し、既存のすべてのセッション属性を新しいセッションにコピーします。これは、Servlet 3.0 以前のコンテナーのデフォルトです。

次のようにして、セッション固定保護を構成できます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement((session) -> session
            .sessionFixation((sessionFixation) -> sessionFixation
                .newSession()
            )
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            sessionFixation {
                newSession()
            }
        }
    }
    return http.build()
}
<http>
  <session-management session-fixation-protection="newSession" />
</http>

セッション固定保護が発生すると、SessionFixationProtectionEvent がアプリケーションコンテキストで公開されます。changeSessionId を使用する場合、この保護により jakarta.servlet.http.HttpSessionIdListener も通知されるため、コードが両方のイベントをリッスンする場合は注意てください。

セッション固定保護を none に設定して無効にすることもできますが、アプリケーションが脆弱なままになるため、これはお勧めできません。

SecurityContextHolderStrategy を使用する

次のコードブロックを検討してください。

  • Java

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
        loginRequest.getUsername(), loginRequest.getPassword());
Authentication authentication = this.authenticationManager.authenticate(token);
// ...
SecurityContext context = SecurityContextHolder.createEmptyContext(); (1)
context.setAuthentication(authentication); (2)
SecurityContextHolder.setContext(context); (3)
  1. SecurityContextHolder に静的にアクセスして、空の SecurityContext インスタンスを作成します。

  2. SecurityContext インスタンスに Authentication オブジェクトを設定します。

  3. SecurityContextHolder に SecurityContext インスタンスを静的に設定します。

上記のコードは正常に動作しますが、望ましくない効果が生じる可能性があります。コンポーネントが SecurityContextHolder を介して静的に SecurityContext にアクセスすると、SecurityContextHolderStrategy を指定するアプリケーションコンテキストが複数ある場合に競合状態が発生する可能性があります。これは、SecurityContextHolder では、アプリケーションコンテキストごとではなく、クラスローダーごとに 1 つの戦略があるためです。

これに対処するために、コンポーネントはアプリケーションコンテキストから SecurityContextHolderStrategy を接続できます。デフォルトでは、依然として SecurityContextHolder から戦略を検索します。

これらの変更は主に内部的なものですが、アプリケーションが SecurityContext に静的にアクセスする代わりに SecurityContextHolderStrategy をオートワイヤーする機会を提供します。そのためには、コードを次のように変更する必要があります。

  • Java

public class SomeClass {

    private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();

    public void someMethod() {
        UsernamePasswordAuthenticationToken token = UsernamePasswordAuthenticationToken.unauthenticated(
                loginRequest.getUsername(), loginRequest.getPassword());
        Authentication authentication = this.authenticationManager.authenticate(token);
        // ...
        SecurityContext context = this.securityContextHolderStrategy.createEmptyContext(); (1)
        context.setAuthentication(authentication); (2)
        this.securityContextHolderStrategy.setContext(context); (3)
    }

}
  1. 構成された SecurityContextHolderStrategy を使用して、空の SecurityContext インスタンスを作成します。

  2. SecurityContext インスタンスに Authentication オブジェクトを設定します。

  3. SecurityContextHolderStrategy に SecurityContext インスタンスを設定します。

Eager セッション作成の強制

先行してセッションを作成することが有益な場合があります。これは、以下を使用して構成できる ForceEagerSessionCreationFilter (Javadoc) を使用して行うことができます。

  • Java

  • Kotlin

  • XML

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http
        .sessionManagement(session -> session
            .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
        );
    return http.build();
}
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http {
        sessionManagement {
            sessionCreationPolicy = SessionCreationPolicy.ALWAYS
        }
    }
    return http.build()
}
<http create-session="ALWAYS">

</http>

次に読むもの

  • Spring Session を使用したクラスター化されたセッション


1. 認証後にフィルターが呼び出されないため、認証後にリダイレクトを実行するメカニズム(フォームログインなど)による認証は SessionManagementFilter によって検出されません。これらの場合、セッション管理機能を個別に処理する必要があります。