最新の安定バージョンについては、Spring Security 6.5.1 を使用してください!

事前認証シナリオ

例としては、X.509、Siteminder、アプリケーションが実行されている Java EE コンテナーによる認証があります。事前認証を使用する場合、Spring Security は

  • リクエストを行っているユーザーを特定します。

  • ユーザーの権限を取得します。

詳細は、外部認証メカニズムによって異なります。ユーザーは、X.509 の場合は証明書情報によって、Siteminder の場合は HTTP リクエストヘッダーによって識別されます。コンテナー認証に依存している場合、ユーザーは受信 HTTP リクエストで getUserPrincipal() メソッドを呼び出すことにより識別されます。場合によっては、外部メカニズムがユーザーにロール / 権限情報を提供することがありますが、別の場合は、UserDetailsService などの別のソースから権限を取得する必要があります。

事前認証フレームワーククラス

ほとんどの事前認証メカニズムは同じパターンに従うため、Spring Security には事前認証された認証プロバイダーを実装するための内部フレームワークを提供するクラスのセットがあります。これにより、重複がなくなり、新しい実装を構造化された方法で追加できるようになり、すべてをゼロから記述する必要がなくなります。X.509 認証のようなものを使用する場合、これらのクラスについて知る必要はありません。すでに使用しやすく、使いやすい名前空間設定オプションがすでにあるためです。明示的な Bean 構成を使用する必要がある場合、または独自の実装の作成を計画している場合は、提供された実装がどのように機能するかを理解しておくと役立ちます。org.springframework.security.web.authentication.preauth にクラスがあります。ここで概要を説明するだけなので、必要に応じて Javadoc とソースを参照してください。

AbstractPreAuthenticatedProcessingFilter

このクラスは、セキュリティコンテキストの現在の内容をチェックし、空の場合、HTTP リクエストからユーザー情報を抽出して AuthenticationManager に送信しようとします。この情報を取得するために、サブクラスは次のメソッドをオーバーライドします。

AbstractPreAuthenticatedProcessingFilter を上書き
  • Java

  • Kotlin

protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);

protected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);
protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?

protected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?

これらを呼び出した後、フィルターは返されたデータを含む PreAuthenticatedAuthenticationToken を作成し、認証のために送信します。ここでの「認証」とは、ユーザーの権限をロードするためのさらなる処理を意味しますが、標準の Spring Security 認証アーキテクチャに従います。

他の Spring Security 認証フィルターと同様に、事前認証フィルターには authenticationDetailsSource プロパティがあり、デフォルトで WebAuthenticationDetails オブジェクトを作成して、Authentication オブジェクトの details プロパティにセッション ID や発信元 IP アドレスなどの追加情報を保存します。事前認証メカニズムからユーザーロール情報を取得できる場合、データもこのプロパティに格納され、詳細が GrantedAuthoritiesContainer インターフェースを実装します。これにより、認証プロバイダーは、ユーザーに外部的に割り当てられた権限を読み取ることができます。次に具体的な例を見てみましょう。

J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource

このクラスのインスタンスである authenticationDetailsSource でフィルターが構成されている場合、権限情報は、「マップ可能なロール」の所定のセットごとに isUserInRole(String role) メソッドを呼び出すことによって取得されます。クラスは、構成された MappableAttributesRetriever からこれらを取得します。可能な実装には、アプリケーションコンテキストでリストをハードコードし、web.xml ファイルの <security-role> 情報からロール情報を読み取ることが含まれます。事前認証サンプルアプリケーションは、後者のアプローチを使用します。

構成された Attributes2GrantedAuthoritiesMapper を使用して、ロール(または属性)が Spring Security GrantedAuthority オブジェクトにマップされる追加の段階があります。デフォルトでは、通常の ROLE_ プレフィックスが名前に追加されますが、動作を完全に制御できます。

PreAuthenticatedAuthenticationProvider

事前認証されたプロバイダーは、ユーザーのために UserDetails オブジェクトをロードする以上のことはほとんどありません。AuthenticationUserDetailsService に委譲することでこれを行います。後者は標準の UserDetailsService に似ていますが、単なるユーザー名ではなく Authentication オブジェクトを取ります。

public interface AuthenticationUserDetailsService {
	UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;
}

このインターフェースには他の用途もありますが、事前認証を使用すると、前のセクションで見たように、Authentication オブジェクトにパッケージ化されたオーソリティにアクセスできます。PreAuthenticatedGrantedAuthoritiesUserDetailsService クラスがこれを行います。または、UserDetailsByNameServiceWrapper 実装を介して標準 UserDetailsService に委譲することもできます。

Http403ForbiddenEntryPoint

AuthenticationEntryPoint は、認証されていないユーザー(保護されたリソースにアクセスしようとした場合)の認証プロセスを開始するロールを果たしますが、事前認証された場合は適用されません。事前認証を他の認証メカニズムと組み合わせて使用しない場合にのみ、このクラスのインスタンスで ExceptionTranslationFilter を構成します。ユーザーが AbstractPreAuthenticatedProcessingFilter によって拒否され、認証が null になった場合に呼び出されます。呼び出されると、常に 403 -forbidden レスポンスコードを返します。

具体的な実装

X.509 認証については、独自の章で説明しています。ここでは、他の事前認証されたシナリオのサポートを提供するいくつかのクラスを見ていきます。

リクエストヘッダー認証 (Siteminder)

外部認証システムは、HTTP リクエストに特定のヘッダーを設定することにより、アプリケーションに情報を提供できます。このよく知られた例は Siteminder で、SM_USER というヘッダーでユーザー名を渡します。このメカニズムは、RequestHeaderAuthenticationFilter クラスによってサポートされており、ヘッダーからユーザー名を抽出するだけです。デフォルトでは、名前 SM_USER がヘッダー名として使用されます。詳細については、Javadoc を参照してください。

このようなシステムを使用する場合、フレームワークは認証チェックをまったく実行しないため、外部システムが適切に構成され、アプリケーションへのすべてのアクセスを保護することが非常に重要です。攻撃者がこれを検出せずに元のリクエストのヘッダーを偽造できる場合、希望するユーザー名を選択する可能性があります。

Siteminder の構成例

このフィルターを使用した典型的な構成は次のようになります。

<security:http>
<!-- Additional http configuration omitted -->
<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</security:http>

<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="SM_USER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>

<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
	<bean id="userDetailsServiceWrapper"
		class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
	<property name="userDetailsService" ref="userDetailsService"/>
	</bean>
</property>
</bean>

<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="preauthAuthProvider" />
</security:authentication-manager>

ここでは、セキュリティ名前空間が構成に使用されていることを前提としています。また、ユーザーのロールをロードするために、構成に UserDetailsService ( "userDetailsService" と呼ばれます) を追加していることも前提としています。

Java EE コンテナー認証

クラス J2eePreAuthenticatedProcessingFilter は、HttpServletRequest の userPrincipal プロパティからユーザー名を抽出します。このフィルターの使用は、通常、上記で J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource で説明した Java EE ロールの使用と組み合わされます。

このアプローチを使用するサンプルプロジェクトにはサンプルアプリケーション [GitHub] (英語) があるため、GitHub からコードを入手し、興味がある場合はアプリケーションコンテキストファイルを確認してください。