17. セキュリティ名前空間の構成

17.1 導入

名前空間構成は、Spring Framework のバージョン 2.0 以降で使用できます。これにより、従来の Spring Bean アプリケーションコンテキスト構文を、追加の XML スキーマの要素で補足できます。詳細については、Spring リファレンスドキュメントを参照してください。名前空間要素は、個々の Bean を構成するより簡潔なメソッドを可能にするために、またはより強力に、問題のドメインにより厳密に一致し、根本的な複雑さをユーザーから隠す代替構成構文を定義するために使用できます。単純な要素は、複数の Bean と処理ステップがアプリケーションコンテキストに追加されているという事実を隠すことができます。例: 次の要素をセキュリティ名前空間からアプリケーションコンテキストに追加すると、アプリケーション内での使用をテストするために組み込み LDAP サーバーが起動します。

<security:ldap-server />

これは、同等の Apache Directory Server Bean を接続するよりもはるかに簡単です。最も一般的な代替構成要件は、ldap-server 要素の属性によってサポートされており、ユーザーは作成する必要のある Bean と Bean プロパティ名について心配する必要がありません。[11] アプリケーションコンテキストファイルの編集中に適切な XML エディターを使用すると、使用可能な属性と要素に関する情報が提供されます。Eclipse Spring Tool Suite (英語) には、標準の Spring 名前空間を操作するための特別な機能があるため、試してみることをお勧めします。

アプリケーションコンテキストでセキュリティ名前空間の使用を開始するには、クラスパスに spring-security-config jar が必要です。あとは、アプリケーションコンテキストファイルにスキーマ宣言を追加するだけです。

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        https://www.springframework.org/schema/security/spring-security.xsd">
    ...
</beans>

表示される多くの例(およびサンプルアプリケーション)では、デフォルトのネームスペースとして「beans」ではなく「security」を使用することがよくあります。つまり、すべてのセキュリティネームスペース要素のプレフィックスを省略して、読みやすい。また、アプリケーションコンテキストを別々のファイルに分割し、それらの 1 つにほとんどのセキュリティ構成がある場合にも、これを行うことができます。セキュリティアプリケーションコンテキストファイルは、このように起動します

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security
        https://www.springframework.org/schema/security/spring-security.xsd">
    ...
</beans:beans>

この章では、この構文が今後使用されると想定します。

17.1.1 名前空間の設計

ネームスペースは、フレームワークの最も一般的な使用をキャプチャーし、アプリケーション内で有効にするための単純化された簡潔な構文を提供するように設計されています。この設計は、フレームワーク内の大規模な依存関係に基づいており、次の領域に分割できます。

  • Web/HTTP セキュリティ - 最も複雑な部分。フレームワーク認証メカニズムの適用、URL の保護、ログインページとエラーページのレンダリングなどに使用されるフィルターと関連サービス Bean を設定します。
  • ビジネスオブジェクト(メソッド)セキュリティ - サービスレイヤーを保護するためのオプション。
  • AuthenticationManager- フレームワークの他の部分からの認証リクエストを処理します。
  • AccessDecisionManager -Web およびメソッドセキュリティのアクセス決定を提供します。デフォルトのものが登録されますが、通常の Spring Bean 構文を使用して宣言されたカスタムのものを選択することもできます。
  • AuthenticationProvider s- 認証マネージャーがユーザーを認証するメカニズム。名前空間は、いくつかの標準オプションをサポートし、従来の構文を使用して宣言されたカスタム Bean を追加する手段も提供します。
  • UserDetailsService- 認証プロバイダーに密接に関連していますが、多くの場合、他の Bean にも必要です。

これらの設定方法については、次のセクションで説明します。

17.2 セキュリティ名前空間の構成の開始

このセクションでは、フレームワークの主な機能のいくつかを使用するために名前空間の構成を構築する方法を見ていきます。最初に、できるだけ早く起動して実行し、いくつかのテストログインで認証サポートとアクセス制御を既存の Web アプリケーションに追加したいとします。次に、データベースまたは他のセキュリティリポジトリに対する認証に切り替える方法を見ていきます。後のセクションで、より高度な名前空間設定オプションを紹介します。

17.2.1 web.xml の構成

最初に行う必要があるのは、web.xml ファイルに次のフィルター宣言を追加することです。

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

これにより、Spring Security Web インフラストラクチャへのフックが提供されます。DelegatingFilterProxy は、アプリケーションコンテキストで Spring Bean として定義されているフィルター実装に委譲する Spring Framework クラスです。この場合、Bean の名前は「springSecurityFilterChain」です。これは、Web セキュリティを処理するためにネームスペースによって作成された内部インフラストラクチャ Bean です。この Bean 名を自分で使用しないでください。これを web.xml に追加したら、アプリケーションコンテキストファイルの編集を開始できます。Web セキュリティサービスは、<http> 要素を使用して構成されます。

17.2.2 最小限の <http> 構成

最初に Web セキュリティを有効にするために必要なのは

<http>
<intercept-url pattern="/**" access="hasRole('USER')" />
<form-login />
<logout />
</http>

これは、アプリケーション内のすべての URL を保護し、それらにアクセスするためにロール ROLE_USER を必要とすること、ユーザー名とパスワードを含むフォームを使用してアプリケーションにログインすること、および許可するログアウト URL を登録することを示しています。アプリケーションからログアウトします。<http> 要素は、すべての Web 関連の名前空間機能の親です。<intercept-url> 要素は、ant パススタイル構文 [12] を使用して、受信リクエストの URL と照合される pattern を定義します。代替として正規表現マッチングを使用することもできます(詳細については、名前空間の付録を参照してください)。access 属性は、指定されたパターンに一致するリクエストのアクセス要件を定義します。デフォルトの構成では、これは通常、コンマで区切られたロールのリストであり、その 1 つはユーザーがリクエストを行うことを許可されている必要があります。接頭辞「ROLE_」は、ユーザーの権限と簡単に比較する必要があることを示すマーカーです。つまり、通常のロールベースのチェックを使用する必要があります。Spring Security のアクセス制御は、単純なロールの使用に限定されていません(したがって、異なるタイプのセキュリティ属性を区別するために接頭辞を使用しています)。[13] の解釈がどのように異なるかについては後で説明します。Spring Security 3.0 では、属性に – 1— を入力することもできます。

[Note] メモ

===

複数の <intercept-url> 要素を使用して、URL の異なるセットに異なるアクセス要件を定義できますが、リストされた順序で評価され、最初に一致したものが使用されます。そのため、最も具体的な一致を上部に配置する必要があります。method 属性を追加して、特定の HTTP メソッド(GETPOSTPUT など)への一致を制限することもできます。

===

ユーザーを追加するには、名前空間で一連のテストデータを直接定義できます。

<authentication-manager>
<authentication-provider>
    <user-service>
    <!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
    NoOpPasswordEncoder should be used. This is not safe for production, but makes reading
    in samples easier. Normally passwords should be hashed using BCrypt -->
    <user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
    </user-service>
</authentication-provider>
</authentication-manager>

これは、同じパスワードを安全に保存する方法の例です。パスワードには {bcrypt} が先頭に付き、DelegatingPasswordEncoder に指示します。DelegatingPasswordEncoder は、マッチングのために構成された PasswordEncoder をサポートし、パスワードは BCrypt を使用してハッシュされます。

<authentication-manager>
<authentication-provider>
    <user-service>
    <user name="jimi" password="{bcrypt}$2a$10$ddEWZUl8aU0GdZPPpy7wbu82dvEw/pBpbRvDQRqA41y6mK1CoH00m"
            authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="{bcrypt}$2a$10$/elFpMBnAYYig6KRR5bvOOYeZr1ie1hSogJryg9qDlhza4oCw1Qka"
            authorities="ROLE_USER" />
    <user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
    </user-service>
</authentication-provider>
</authentication-manager>

上記の構成では、2 人のユーザー、パスワード、アプリケーション内のロール(アクセス制御に使用されます)を定義します。user-service の properties 属性を使用して、標準プロパティファイルからユーザー情報をロードすることもできます。ファイル形式の詳細については、メモリ内認証のセクションを参照してください。<authentication-provider> 要素を使用するということは、認証マネージャーがユーザー情報を使用して認証リクエストを処理することを意味します。異なる認証ソースを定義するために複数の <authentication-provider> 要素を使用でき、それぞれが順番に調べられます。

この時点で、アプリケーションを起動できるようになり、続行するにはログインする必要があります。試してみるか、プロジェクトに付属している「チュートリアル」サンプルアプリケーションを試してみてください。

デフォルトのログイン後の宛先の設定

保護されたリソースへのアクセスの試行によってフォームログインがプロンプトされない場合、default-target-url オプションが機能します。これは、ユーザーが正常にログインした後に取得される URL であり、デフォルトは「/".」です。ユーザーが常にこのページにアクセスするように構成することもできます(ログインが「オンデマンド」であったか、明示的に行われたかに関係なく)。always-use-default-target 属性を「true」に設定してログインすることを選択しました。これは、アプリケーションでユーザーが常に「ホーム」ページから開始する必要がある場合に役立ちます。例:

<http pattern="/login.htm*" security="none"/>
<http use-expressions="false">
<intercept-url pattern='/**' access='ROLE_USER' />
<form-login login-page='/login.htm' default-target-url='/home.htm'
        always-use-default-target='true' />
</http>

宛先をさらに制御するには、authentication-success-handler-ref 属性を default-target-url の代替として使用できます。参照される Bean は AuthenticationSuccessHandler のインスタンスでなければなりません。これについては、コアフィルターの章と名前空間の付録、および認証が失敗したときにフローをカスタマイズする方法に関する情報を参照してください。

17.3 高度な Web 機能

17.3.1 独自のフィルターを追加する

以前に Spring Security を使用したことがある場合、フレームワークはサービスを適用するためにチェーンのフィルターを保持していることがわかります。特定の場所でスタックに独自のフィルターを追加するか、現在ネームスペース構成オプション(CAS など)がない Spring Security フィルターを使用することができます。または、<form-login> 要素によって作成される UsernamePasswordAuthenticationFilter など、標準の名前空間フィルターのカスタマイズされたバージョンを使用し、Bean を明示的に使用することで利用できる追加の構成オプションのいくつかを利用することもできます。フィルターチェーンは直接公開されていないため、名前空間の構成でこれを行うにはどうすればよいですか?

ネームスペースを使用する場合、フィルターの順序は常に厳密に適用されます。アプリケーションコンテキストが作成されると、フィルター Bean はネームスペース処理コードによってソートされ、標準の Spring Security フィルターはそれぞれ、ネームスペース内のエイリアスと既知の位置を持ちます。

[Note] メモ

=== 以前のバージョンでは、フィルターインスタンスが作成された後、アプリケーションコンテキストの後処理中に並べ替えが行われました。バージョン 3.0 + では、クラスがインスタンス化される前に、Bean メタデータレベルでソートが行われるようになりました。これは、<http> 要素の解析中にフィルターリスト全体を認識している必要があるため、独自のフィルターをスタックに追加する方法に影響を与えるため、3.0 では構文がわずかに変更されています。===

フィルターを作成するフィルター、エイリアス、ネームスペース要素 / 属性はテーブル 17.1: “ 標準のフィルターエイリアスと順序 ” に示されています。フィルターは、フィルターチェーンで発生する順序でリストされています。

テーブル 17.1: 標準のフィルターエイリアスと順序

エイリアス フィルタークラス 名前空間要素または属性

CHANNEL_FILTER

ChannelProcessingFilter

http/[email protected] (英語)

SECURITY_CONTEXT_FILTER

SecurityContextPersistenceFilter

http

CONCURRENT_SESSION_FILTER

ConcurrentSessionFilter

session-management/concurrency-control

HEADERS_FILTER

HeaderWriterFilter

http/headers

CSRF_FILTER

CsrfFilter

http/csrf

LOGOUT_FILTER

LogoutFilter

http/logout

X509_FILTER

X509AuthenticationFilter

http/x509

PRE_AUTH_FILTER

AbstractPreAuthenticatedProcessingFilter サブクラス

なし

CAS_FILTER

CasAuthenticationFilter

なし

FORM_LOGIN_FILTER

UsernamePasswordAuthenticationFilter

http/form-login

BASIC_AUTH_FILTER

BasicAuthenticationFilter

http/http-basic

SERVLET_API_SUPPORT_FILTER

SecurityContextHolderAwareRequestFilter

http/@servlet-api-provision

JAAS_API_SUPPORT_FILTER

JaasApiIntegrationFilter

http/@jaas-api-provision

REMEMBER_ME_FILTER

RememberMeAuthenticationFilter

http/remember-me

ANONYMOUS_FILTER

AnonymousAuthenticationFilter

http/anonymous

SESSION_MANAGEMENT_FILTER

SessionManagementFilter

session-management

EXCEPTION_TRANSLATION_FILTER

ExceptionTranslationFilter

http

FILTER_SECURITY_INTERCEPTOR

FilterSecurityInterceptor

http

SWITCH_USER_FILTER

SwitchUserFilter

なし


custom-filter 要素とこれらの名前のいずれかを使用して独自のフィルターをスタックに追加し、フィルターが表示される位置を指定できます。

<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
</http>

<beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>

スタック内の別のフィルターの前または後にフィルターを挿入する場合は、after または before 属性を使用することもできます。「FIRST」および「LAST」という名前を position 属性とともに使用して、フィルターをスタック全体の前または後に表示することをそれぞれ示すことができます。

[Tip] フィルター位置の競合の回避

===

名前空間によって作成された標準フィルターの 1 つと同じ位置を占める可能性のあるカスタムフィルターを挿入する場合、名前空間バージョンを誤って含めないことが重要です。機能を置き換えるフィルターを作成する要素を削除します。

<http> 要素自体を使用して作成されたフィルター(SecurityContextPersistenceFilterExceptionTranslationFilter、または FilterSecurityInterceptor)を置き換えることはできません。他のいくつかのフィルターはデフォルトで追加されますが、無効にすることができます。AnonymousAuthenticationFilter はデフォルトで追加され、セッション固定保護を無効にしない限り、SessionManagementFilter もフィルターチェーンに追加されます。

===

認証エントリポイントを必要とする名前空間フィルターを置き換える場合(つまり、認証されていないユーザーがセキュリティで保護されたリソースにアクセスしようとすると認証プロセスがトリガーされる場合)、カスタムエントリポイント Bean も追加する必要があります。

17.4 メソッドのセキュリティ

バージョン 2.0 以降、Spring Security はサービスレイヤーメソッドにセキュリティを追加するためのサポートを大幅に改善しました。JSR-250 アノテーションセキュリティおよびフレームワークの元の @Secured アノテーションのサポートを提供します。3.0 から、新しい式ベースのアノテーションを利用することもできます。intercept-methods 要素を使用して Bean 宣言を装飾し、単一の Bean にセキュリティを適用するか、AspectJ スタイルのポイントカットを使用してサービスレイヤー全体で複数の Bean を保護できます。

17.5 デフォルトの AccessDecisionManager

このセクションでは、Spring Security 内のアクセス制御の基礎となるアーキテクチャに関する知識があることを前提としています。このセクションは、単純なロールベースのセキュリティ以上のものを使用するためにカスタマイズを行う必要のある人にのみ関連するため、スキップして後で戻ることができます。

ネームスペース構成を使用すると、AccessDecisionManager のデフォルトインスタンスが自動的に登録され、intercept-url および protect-pointcut 宣言(およびアノテーション)で指定したアクセス属性に基づいて、メソッド呼び出しおよび Web URL アクセスのアクセス決定に使用されます。アノテーションで protected メソッドを使用している場合)。

デフォルトの戦略は、AffirmativeBased AccessDecisionManager を RoleVoter および AuthenticatedVoter とともに使用することです。これらの詳細については、認可の章を参照してください。

17.5.1 AccessDecisionManager のカスタマイズ

より複雑なアクセス制御戦略を使用する必要がある場合は、メソッドと Web セキュリティの両方の代替手段を簡単に設定できます。

メソッドのセキュリティを確保するには、アプリケーションコンテキストで global-method-security の access-decision-manager-ref 属性を適切な AccessDecisionManager Bean の id に設定します。

<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
...
</global-method-security>

Web セキュリティの構文は同じですが、http 要素にあります:

<http access-decision-manager-ref="myAccessDecisionManagerBean">
...
</http>


[11] セクション 10.3: “LDAP 認証 ” の章で ldap-server 要素の使用について詳しく知ることができます。

[12] 一致が実際に実行される方法の詳細については、Web アプリケーションインフラストラクチャの章の ??? に関するセクションを参照してください。

[13] access 属性のコンマ区切り値の解釈は、使用される AccessDecisionManager の実装に依存します。

現行バージョンへ切り替える