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

事前認証シナリオ

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

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

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

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

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

ほとんどの事前認証メカニズムは同じパターンに従うため、Spring Security には、事前認証された認証プロバイダーを実装するための内部フレームワークを提供する一連のクラスがあります。これにより、重複がなくなり、すべてを最初から作成しなくても、構造化された方法で新しい実装を追加できます。X.509 認証のようなものを使用する場合は、これらのクラスについて知る必要はありません。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 オブジェクトを作成して、セッション ID や発信元 IP アドレスなどの追加情報を Authentication オブジェクトの details プロパティに格納します。事前認証メカニズムからユーザーロール情報を取得できる場合は、データもこのプロパティに格納され、詳細は 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 からコードを入手し、興味がある場合はアプリケーションコンテキストファイルを確認してください。