http://kagamihoge.hatenablog.com/entry/2017/05/17/234536 の続き。
5.8 Method Security
version 2.0以降のSpring Securityではサービスレイヤーのメソッドにセキュリティを付与する機能が大幅に進化しました。フレームワーク固有の@Secured
アノテーションと共にJSR-250アノテーションセキュリティをサポートしています。また、3.0からは新たにexpression-based annotationsも使用可能です。ビーン宣言に付与するintercept-methods
要素で単一のビーンにセキュリティを適用したり、AspectJスタイルのポイントカットでサービスレイヤー全体で横断的に複数のビーンにセキュリティを適用できます。
5.8.1 EnableGlobalMethodSecurity
@Configuration
インスタンスに@EnableGlobalMethodSecurity
を付与することでアノテーションベースのセキュリティを有効化できます。例えば、以下はSpring Securityの@Secured
アノテーションを有効化しています。
@EnableGlobalMethodSecurity(securedEnabled = true) public class MethodSecurityConfig { // ... }
メソッド(もしくはクラスかインタフェース)にアノテーションを付与することでそのメソッドへのアクセスが制限されるようになります。Spring Security固有のアノテーションではメソッドに対する属性を定義します。その属性はAccessDecisionManagerに渡されて何らかの判定が行われます。
public interface BankService { @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account readAccount(Long id); @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account[] findAccounts(); @Secured("ROLE_TELLER") public Account post(Account account, double amount); }
JSR-250アノテーションを有効化することも出来ます。
@EnableGlobalMethodSecurity(jsr250Enabled = true) public class MethodSecurityConfig { // ... }
上記は標準ベースで単純なロールベースの制約を適用できますが、豊富なSpring Security固有のアノテーションを使えません。expression-based syntaxを使うには以下のようにします。
@EnableGlobalMethodSecurity(prePostEnabled = true) public class MethodSecurityConfig { // ... }
Spring Security固有の例と同等なコードは以下のようになります。
public interface BankService { @PreAuthorize("isAnonymous()") public Account readAccount(Long id); @PreAuthorize("isAnonymous()") public Account[] findAccounts(); @PreAuthorize("hasAuthority('ROLE_TELLER')") public Account post(Account account, double amount); }
5.8.2 GlobalMethodSecurityConfiguration
場合によっては@EnableGlobalMethodSecurity
アノテーションで出来る以上の複雑なオペレーションが必要となるケースがあります。その場合、GlobalMethodSecurityConfiguration
を拡張し、そのサブクラスに@EnableGlobalMethodSecurity
アノテーションを付与します。例えば、MethodSecurityExpressionHandler
をカスタムしたい場合、以下のような設定にします。
@EnableGlobalMethodSecurity(prePostEnabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { @Override protected MethodSecurityExpressionHandler createExpressionHandler() { // ... 自前のMethodSecurityExpressionHandlerを作成してreturnする ... return expressionHandler; } }
オーバーライド可能なメソッドに関する詳細についてはGlobalMethodSecurityConfiguration
のjavadocを参照してください。
5.9 Post Processing Configured Objects
Spring SecurityのJava Configurationは設定が行われるオブジェクトのすべてのプロパティを公開してはいません。これにより大多数のユーザ向けに設定を簡易化しています。すべてのプロパティが公開されたとして、どちらにせよ一般的なビーン設定を使うことになります。*1
すべてのプロパティへの直接アクセスをさせない理由には正当性がありますが、より高度な設定オプションを使いたいケースも当然ながらあり得ます。Spring SecurityはObjectPostProcessor
の概念を導入しており、これによりJava Configurationが生成する多数のオブジェクトのインスタンスを変更あるいは置き換えられます。たとえば、FilterSecurityInterceptor
のfilterSecurityPublishAuthorizationSuccess
プロパティを設定する場合は以下のようになります。
@Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { public <O extends FilterSecurityInterceptor> O postProcess( O fsi) { fsi.setPublishAuthorizationSuccess(true); return fsi; } }); }
5.10 Custom DSLs
Spring Securityの自前のDSLを指定できます。たとえば、以下のようなものです。。
public class MyCustomDsl extends AbstractHttpConfigurer<CorsConfigurerMyCustomDsl, HttpSecurity> { private boolean flag; @Override public void init(H http) throws Exception { // initメソッドで必要なconfigurerを追加するメソッド // があればここに書く。 http.csrf().disable(); } @Override public void configure(H http) throws Exception { ApplicationContext context = http.getSharedObject(ApplicationContext.class); // ここでApplicationContextからルックアップしている。 // 新規インスタンスをここで生成可能。 MyFilter myFilter = context.getBean(MyFilter.class); myFilter.setFlag(flag); http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class); } public MyCustomDsl flag(boolean value) { this.flag = value; return this; } public static MyCustomDsl customDsl() { return new MyCustomDsl(); } }
上記はHttpSecurity.authorizeRequests()
の実際の実装に近いです。
自前のDSLは以下のようにして使います。
@EnableWebSecurity public class Config extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .apply(customDsl()) .flag(true) .and() ...; } }
このコードは以下の順序で実行されます。
- ‘Config'のconfigureメソッドが実行される。
- ‘MyCustomDsl'のinitメソッドが実行される。
- ‘MyCustomDsl'のconfigureメソッドが実行される。
なお、SpringFactories
を使用してWebSecurityConfiguerAdapter
とMyCustomDsl
をデフォルトにできます。たとえば、以下の内容をクラスパス下にMETA-INF/spring.factories
という名前のファイルとして作成します。
META-INF/spring.factories.
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer = sample.MyCustomDsl
デフォルトを無効化する場合はそれを明示します。
@EnableWebSecurity public class Config extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .apply(customDsl()).disable() ...; } }
6. Security Namespace Configuration
6.1 Introduction
Namespace configurationはSpring Frameworkのバージョン2.0から利用可能となっています。これは従来型のSpring beanアプリケーションコンテキストのシンタックスを追加のXMLスキーマによって補うものです。詳細についてはReference Documentationを参照してください。namespaceの要素を使うことで個々のbeanの設定方法が簡潔でシンプルになり、問題領域と一致させやすい設定のシンタックスを別途定義することで基礎部分の複雑さをユーザから隠蔽します。シンプルな要素でアプリケーションコンテキストに追加される処理ステップと複数のbeanを隠蔽します。たとえば、以下のsecurity namespace要素をアプリケーションに追加すると、アプリケーション内にテスト用の組み込みLDAPサーバが起動します。
<security:ldap-server />
同じことをするApache Directory Serverのbeanをワイヤリングするのに比べればかなりシンプルです。よくある設定のための属性がldap-server
要素に用意されており、beanのプロパティ名やbean生成に関しては調べる必要はありません。[1]. アプリケーションコンテキストファイル編集の際には頭の良いXMLエディタを使用すると使用可能な要素と属性をアシストしてくれます。Spring Tool Suiteを推奨し、これはSpring namespacesをサポートする特別な機能があります。
[1] - ldap-server
要素の詳細についてはChapter 29, LDAP Authenticationを参照してください。
アプリケーションコンテキストでsecurity namespaceを使うには、まずクラスパスに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 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> ... </beans>
リファレンス内のサンプルの多く(とサンプルアプリケーション)は、デフォルトnamespaceに"beans"ではなく"security"を使いますが、これは読みやすさのためで、すべてのsecurity namespace要素からプレフィクスを省略するためです。また、アプリケーションコンテキストを別々のファイルに分割し、そのファイルの一つにセキュリティ設定の大半を詰め込みたい場合にもこのようにします。この場合のアプリケーションコンテキストファイルは以下のようになります。
<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 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> ... </beans:beans>
このチャプターでは上記のシンタックスを使用していると仮定します。
6.1.1 Design of the Namespace
namespaceはフレームワークの最も一般的な使い方を捉えて、シンプルかつ簡潔なシンタックスでアプリケーションを設定出来るように設計されています。この設計はフレームワークの様々な依存性全体をベースに出来ており、以下の領域に分けられます。
- Web/HTTP Security - 一番複雑な部分。フィルタと関連サービスbeanをセットアップする。beanはフレームワークの認証メカニズムを適用するのに使われ、URLのセキュア化、ログインとエラーページなどのレンダリングを行う。
- Business Object (Method) Security -サービスレイヤをセキュア化するためのオプション。
- AuthenticationManager - フレームワークの他部分からの認証リクエストの処理を担当。
- AccessDecisionManager - webとメソッドセキュリティでのアクセス判断を行う。デフォルト実装が登録されるが、一般的なSpring bean宣言でそれとは別のカスタム実装を選択可能。
- AuthenticationProviders - 認証マネージャがユーザを認証する際のメカニズム。namespaceは複数の標準的なオプションをサポートしつつ、従来型のカスタムbean宣言で追加することも可能。
- UserDetailsService - 認証プロバイダと密接に関連するものだが、別のbeanがこれを要求することがある。
以降のセクションでこれらの設定方法について見ていきます。
6.2 Getting Started with Security Namespace Configuration
このセクションでは、フレームワークの主要機能のいくつかをnamespace configurationで設定する方法を見ていきます。まず最初に、なるべく早く動くものを作成して認証サポートを追加して既存のwebアプリケーションにテスト用のログインユーザにアクセス制御をつける、をやっていきます。次に、データベースもしくは別のセキュリティリポジトリを使用した認証への変更を見ていきます。それ以降のセクションでは高度なnamespace configurationオプションを紹介します。
6.2.1 web.xml Configuration
まず以下のフィルター宣言を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 Frameworkのクラスで、アプリケーションコンテキストでSpringのbeanとして定義してあるフィルタ実装へ移譲を行います。上の場合、bean名は"springSecurityFilterChain"で、これはnamespaceが生成する内部的な基盤beanで、webセキュリティを処理します。なお、このbean名を別のbeanには使用してはいけません。web.xml
に上記を追加してから、アプリケーションコンテキストファイルを編集します。<http>
要素を使用してWeb security serviceを設定します。
6.2.2 A Minimal Configuration
webセキュリティの有効化はまず以下のようにします。
<http> <intercept-url pattern="/**" access="hasRole('USER')" /> <form-login /> <logout /> </http>
上記設定の意味は、アプリケーション内の全URLをセキュア化し、その全URLへのアクセスにROLE_USER
ロールを要求し、ユーザ名とパスワードのフォームでアプリケーションにログインを行うようにして、アプリケーションでログアウトするためのURLが用意されます。<http>
要素は、web関連のすべてのnamespace機能の親要素です。<intercept-url>
要素にはantパスシンタックスでリクエストURLにマッチングさせるpattern
を定義します[2]。なお、正規表現によるマッチングも可能です(詳細はnamaspaces appendixを参照)。access
属性はパターンにマッチしたリクエストに対するアクセス要求を定義します。デフォルト設定では、ロールのカンマ区切りリストで、アクセスが許可されるにはユーザはそのうちの一つを持っている必要があります。プレフィクス"ROLE_“はユーザの権限が単純比較で行われることを示すマーカーです。つまり、normal role-based checkが行われる、ということです*2。Spring Securityのアクセス制御は単純なロール以外もあります(つまり異なる種類のセキュリティ属性を区別するのにプレフィクスを使用する)。その処理の詳細については後で見ます。footnote:[The interpretation of the comma-separated values in the access attribute depends on the implementation of the -1- which is used. In Spring Security 3.0, the attribute can also be populated with an -2-.*3
[2] - マッチングの詳細についてはWeb Application InfrastructureのSection 13.4, “Request Matching and HttpFirewall”を参照してください。
異なるURLで異なるアクセス要求を定義するのに複数の<intercept-url>
要素を使用でき、リスト順に評価されて最初にマッチしたものが使われます。よって、リストのトップに最も広くマッチするものを置く必要があります。また、特定のHTTPメソッド(GET
, POST
, PUT
など)のマッチに制限するのにmethod
属性が使えます。
テストユーザを何人か追加するには、namespaceに直接テストデータを追加します。
<authentication-manager> <authentication-provider> <user-service> <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="bob" password="bobspassword" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
フレームワークのnamespace以前のバージョンの知識がある場合、上記で何が行われているか大まかに推測できるかと思います。<http>
要素はFilterChainProxy
を生成する責務を負い、要素で使うビーンをフィルタリングします。フィルタの順序間違いなどのありがちな問題は、フィルタのポジションが予め定義されるため、問題にならなくなりました。
<authentication-provider>
要素はDaoAuthenticationProvider
beanを生成し、<user-service>
要素はInMemoryDaoImpl
を生成します。すべてのauthentication-provider
要素は<authentication-manager>
の子要素である必要があり、<authentication-manager>
はProviderManager
を生成して認証プロバイダを登録します。生成されるbeanの詳細についてはnamespace appendixを参照してください。フレームワークの重要なクラスとその使われ方を理解したくなった場合、とくにカスタマイズをする場合は、namespace appendixを活用してください。
上記設定例では、アプリケーションにおける(アクセス制御に使われる)パスワードとロール、二人のユーザを定義しています。user-service
のproperties
属性でプロパティファイルからユーザ情報をロードするようにも出来ます。ファイルフォーマットの詳細についてはin-memory authenticationを参照してください。<authentication-provider>
要素は、認証リクエストを処理する認証マネージャが使用するユーザ情報を指定します。異なるアプリケーションソースをを定義するのに複数の<authentication-provider>
要素を使用可能で、順番に処理されます。
以上でアプリケーションを開始可能となりログインが要求されます。設定を書いて試すか、"tutorial"サンプリケーションで試してみてください。
6.2.3 Form and Basic Login Options
ログインをしようとした時にログインフォームがどこから来たのか、HTMLやJSPを何も用意していないので、疑問に感じたかもしれません。実際、ログインページ用のURLを明示的に設定しない場合、Spring Securityは、デフォルト値で有効化される機能でログインのサブミットを処理するURLでログインページを自動生成し、デフォルトのターゲットURLがログイン後にユーザに送られます。なお、namaspaceはカスタマイズ可能なオプションを多数用意しています。たとえば、自前のログインページを表示したい場合、以下のようにします。
<http> <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page='/login.jsp'/> </http>
追加でintercept-url
要素を足しており、これはログインページに対するリクエストをアノニマスユーザで利用可能にしています。[3] IS_AUTHENTICATED_ANONYMOUSLY
の詳細はAuthenticatedVoterを参照してください。ログインページ以外へのリクエストはパターン/**
にマッチし、このパターンではログインページにアクセス出来なくなります。これは良くある設定エラーでアプリケーションは無限ループになります。ログインページがセキュアと考えられる場合、Spring Securityはwarningログを出します*4。特定パターンにマッチするすべてのリクエストがセキュリティフィルターチェーンをバイパスする設定が可能で、これは以下のようにパターンごとに別々のhttp
要素を定義します。
[3] - Chapter 22, Anonymous Authenticationを参照。
<http pattern="/css/**" security="none"/> <http pattern="/login.jsp*" security="none"/> <http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page='/login.jsp'/> </http>
Spring Security 3.1以降、異なるリクエストパターンごとのセキュリティフィルターチェーン設定を定義するのに複数のhttp
要素を使用可能です。http
要素にpattern
属性を書かない場合、すべてのリクエストにマッチします。非セキュアなパターンの作成はこのシンタックスの一例で、ここでのパターンは空のフィルターチェーンが関連付けされます。[4] このシンタックスの詳細についてはSecurity Filter Chainを参照してください。
[4] - 複数<http>
要素は重要な機能で、例えば、同一アプリケーションでステートフルとステートレスのパス両方を同時に実現出来ます。この機能追加は、以前のシンタックスである、intercept-url
要素のfilters="none"
属性とは非互換で、3.1では未サポートです。
これら非セキュアなリクエストはSpring Securityのweb関連configurationやrequires-channel
などの属性から完全に関知されなくなる点は重要で*5、そのリクエストにおいてカレントユーザの情報にアクセスしたりセキュアなメソッド呼び出しが出来ません。その場合でもセキュリティフィルタチェーンを適用したい場合、代わりにaccess='IS_AUTHENTICATED_ANONYMOUSLY'
を使用してください。
フォームログインではなくベーシック認証を使いたい場合、設定を変更します。
<http use-expressions="false"> <intercept-url pattern="/**" access="ROLE_USER" /> <http-basic /> </http>
ベーシック認証が優先され、ユーザが保護リソースにアクセスしようとした場合にログインプロンプトが使われます。この設定でもフォーム認証は利用可能で、例えば別のwebページに埋め込んだログインフォームを使います。
Setting a Default Post-Login Destination
If a form login isn’t prompted by an attempt to access a protected resource, default-target-url
オプションが有効になります。ユーザがログイン成功時に得るURLでフォルトは"/"
です。always-use-default-target
属性をtrueに設定することでこのページに(ログインが必要になった段階か明示的にログインを選んだかに関わらず)常に進むように設定出来ます。アプリケーションでユーザが常に"home"ページに進む場合に役立ちます。
<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>
ログイン後のページ遷移のより細かい制御については、default-target-url
の代わりにauthentication-success-handler-ref
属性を使います。このbeanはAuthenticationSuccessHandler
のインスタンスになります。詳細はCore Filtersとnamespace appendix、また認証失敗時のフローのカスタマイズ方法の情報も参照してください。
6.2.4 Logout Handling
logout
要素で特定URLへの遷移によるログアウト機能を設定します。デフォルトのログアウトURLは/logout
で、logout-url
属性で別のURLを設定します。その他に利用可能な属性についてはnamespace appendixを参照してください。
6.2.5 Using other Authentication Providers
現実的には、ユーザ情報のソースにはアプリケーションコンテキストに少数名を追加するのではなく、よりスケーラブルなものを使うかと思います。たいていの場合、LDAPサーバやデータベースなど何らかの媒体にユーザ情報を格納しています。LDAP namespace configurationはLDAP chapterで扱うため、ここでは説明しません。いま、アプリケーションコンテキストに"myUserDetailsService"というbean名でSpring SecurityのUserDetailsService
実装があると仮定すると、認証でこれを使うには以下のようにします。
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager>
データベースを使う場合は以下のようにします。
<authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="securityDataSource"/> </authentication-provider> </authentication-manager>
ここでの"securityDataSource"はアプリケーションコンテキスト内のDataSource
を指すbean名で、Spring Security決め打ちのuser data tablesを持つデータベースを指します。もしくは、Spring SecurityのJdbcDaoImpl
beanを設定してuser-service-ref
でそのbeanを使うことも出来ます。
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager> <beans:bean id="myUserDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"> <beans:property name="dataSource" ref="dataSource"/> </beans:bean>
以下のようにAuthenticationProvider
beanを使うこともできます。
<authentication-manager> <authentication-provider ref='myAuthenticationProvider'/> </authentication-manager>
ここでのmyAuthenticationProvider
はアプリケーションコンテキストでAuthenticationProvider
を実装するbean名です。複数のauthentication-provider
要素を使用可能で、その場合には個々のプロバイダは宣言順に実行されます。namespaceでのSpring SecurityのAuthenticationManager
設定方法の詳細についてはSection 6.6, “The Authentication Manager and the Namespace”を参照してください。
Adding a Password Encoder
パスワードはいかなる場合でもセキュリティ用途(SHAやMD5のような汎用アルゴリズムでは無く)に設計されたハッシュアルゴリズムを使うべきです。<password-encoder>
要素でこれを指定します。bcryptエンコードのパスワードを使う場合、大本に認証プロバイダ設定は以下のようになります。
<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/> <authentication-manager> <authentication-provider> <password-encoder ref="bcryptEncoder"/> <user-service> <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager>
bcryptはおおよそのケースに適していますが、レガシーシステムによって別のアルゴリズムを強いられる場合は除きます。今現在、単純なハッシュアルゴリズムであるとか、もっと悪い、パスワードをプレーンテキストで保存しているとかの場合、bcryptなどセキュアな方針への移行を検討すべきです。
6.3 Advanced Web Features
6.3.1 Remember-Me Authentication
remember-me namespace configurationについてはRemember-Me chapterを参照してください。
6.3.2 Adding HTTP/HTTPS Channel Security
アプリケーションがHTTPとHTTPS双方をサポートする場合、特定のURLのみHTTPSでアクセス可能にする必要があり、その場合は<intercept-url>
属性のrequires-channel
で設定します。
<http> <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/> <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/> ... </http>
上記の設定の場合、ユーザがHTTPで"/secure/**“にマッチするURLにアクセスしようとすると、HTTPS URL [5] にリダイレクトされます。利用可能なオプションは"http”, “https” or “any"です。"any"はHTTPかHTTPSのどちらかを使用する、という意味です。
[5] - channel-processingの実装の詳細については、ChannelProcessingFilter
とその関連クラスのjavadocを参照してください。
HTTPのどちらかHTTPSまたは両方で非標準のポートを使う場合、以下のようなport mappingを指定します。
<http> ... <port-mappings> <port-mapping http="9080" https="9443"/> </port-mappings> </http>
真にセキュアにするのであれば、アプリケーションはHTTPを全く使わなくしたり、HTTPとHTTPSの切り替えはやらない方が良いです。HTTPSで開始(ユーザは最初からHTTPS URLでアクセス)し、中間者攻撃の可能性を回避するために常にセキュアな接続を使用すべきです。
6.3.3 Session Management
Detecting Timeouts
Spring Securityでは無効なセッションIDを検出して適当なURLにユーザをリダイレクトする設定が可能です。これはsession-management
要素で設定します。
<http> ... <session-management invalid-session-url="/invalidSession.htm" /> </http>
この方法でセッションタイムアウトを検出する場合、ユーザがログアウト後にブラウザを閉じずに再ログインすると誤ったエラーを報告する可能性があります。これはセッション無効化時にセッションクッキーをクリアしないためで、たとえユーザがログアウトしていても再度サブミットします。ログアウトハンドラーで以下のようなシンタックスによって、ログアウト時にJSESSIONIDクッキーを明示的に削除できます。
<http> <logout delete-cookies="JSESSIONID" /> </http>
残念ながらこの設定はすべてのサーブレットコンテナでの動作は保証していないため、個々の環境で動作するかどうかの確認が必要です。
プロキシを介してアプリケーションを動作させる場合、プロキシサーバの設定でセッションクッキーを削除できる場合があります。たとえば、Apache HTTPDのmod_headersでは、以下のディレクティブはログアウトリクエストのレスポンスでクッキーを期限切れにすることでJSESSIONID
を削除しています(以下の例は/tutorial
パス下にアプリケーションをデプロイしていると仮定)。
<LocationMatch "/tutorial/logout"> Header always set Set-Cookie "JSESSIONID=;Path=/tutorial;Expires=Thu, 01 Jan 1970 00:00:00 GMT" </LocationMatch>
Concurrent Session Control
アプリケーションでユーザのログインを単一に制約したい場合があり、Spring Securityは以下のようにちょっとした設定でそれを実現できます。まずweb.xml
ファイルに以下のリスナーを追加してセッションライフサイクルイベントをSpring Securityで受け取れるように変更します。
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
次にアプリケーションコンテキストに以下の行を追加します。
<http> ... <session-management> <concurrency-control max-sessions="1" /> </session-management> </http>
これによりユーザは複数回ログイン出来なくなり、二回目のログインは一回目のログインを無効化します。二回目のログインを抑止したい場合は以下のようにします。
<http> ... <session-management> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /> </session-management> </http>
こうすると二回目のログインは拒否されます。拒否(“rejected”)されると、フォームベースのログインを使っている場合はユーザはauthentication-failure-url
に送られます。二回目の認証は “remember-me"など対話的でない方法で行われる場合があり、"unauthorized” (401) エラーがクライアントに送られます。そうではなくエラーページにしたい場合、session-management
要素にsession-authentication-error-url
属性を追加します。
フォームベースのログインでカスタマイズした認証フィルタを使用する場合、明示的にconcurrent session control機能を設定する必要があります。詳細はSession Management chapterを参照してください。
Session Fixation Attack Protection
Session fixation攻撃とはサイトアクセス時に悪意のあるアタッカーがセッションを生成する可能性のある潜在的リスクで、同一のセッションを用いてログインするようユーザを仕向けます(たとえばパラメータとしてセッション識別子を含むリンクをユーザに送るなど)。Spring Securityではこれを、ユーザログイン時に新規セッションを生成するかセッションIDを変更して、自動的に防止します。これが必要でない場合、もしくは他の機能とコンフリクトする場合、<session-management>
のsession-fixation-protection
属性で振る舞いを制御します。
none
- 何もしない。元のセッションは残り続ける。newSession
- 新規の"クリーンな(clean)“セッションを生成し、既存のセッションデータはコピーしない(Spring Securiy関連の属性はコピーされる)。migrateSession
- 新規セッションを生成してすべての既存のセッション属性を新規セッションにコピーする。Servlet 3.0もしくはそれより古いコンテナの場合のデフォルト。changeSessionId
- 新規セッションを生成しない。ただしServletコンテナが提供するsession fixation protectionを使用する(HttpServletRequest#changeSessionId()
)。このオプションはServlet 3.1 (Java EE 7)およびそれ以降のコンテナでのみ使用可能。古いコンテナで指定すると例外をスローする。Servlet 3.1およびそれ以降のコンテナの場合のデフォルト。
session fixationに対する防御が発生すると、アプリケーションコンテキストにSessionFixationProtectionEvent
がパブリッシュされます。また、changeSessionId
を使う場合、防御発生時にはjavax.servlet.http.HttpSessionIdListener
に通知されます。両イベントをリッスンする場合には慎重に使って下さい*6。詳細についてはSession Managementを参照してください。
6.3.4 OpenID Support
namespaceではフォームログインの他にOpenIDログインをサポートしており、設定を以下のように変更します。
<http> <intercept-url pattern="/**" access="ROLE_USER" /> <openid-login /> </http>
OpenIDプロバイダ(myopenid.comなど)に情報を登録し、<user-service>
でインメモリにユーザ情報を追加します。
<user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
認証を行うためにmyopenid.com
サイトでログイン可能な状態にしておきます。なお、openid-login
要素のuser-service-ref
属性にOpenIDを扱う別のUserDetailsService
を指定可能です。詳細は前述のauthentication providersを参照してください。注意点として、上のユーザ設定ではパスワード属性を省略していますが、これはユーザデータがauthoritiesをロードするためだけに使われるからです。内部的にランダムパスワードが生成され、設定の認証ソースとしてこのユーザデータを誤って使ってしまうことを防いでいます。
Attribute Exchange
OpenIDのattribute exchangeをサポートしています。例として、以下の設定はOpenIDプロバイダからemailとフルネームを取得します。
<openid-login> <attribute-exchange> <openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/> <openid-attribute name="name" type="http://axschema.org/namePerson"/> </attribute-exchange> </openid-login>
OpenID属性の"type"は固有のスキーマで表現されるURIで、例えばhttp://axschema.org/などです。認証を正常終了させるのにその属性の取得が必須であれば、required
属性を設定します。サポートされる正確なスキーマと属性はOpenIDプロバイダに依存します。属性値は認証処理の一部として返され、以下のようなコードでアクセスします。
OpenIDAuthenticationToken token = (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication(); List<OpenIDAttribute> attributes = token.getAttributes();
OpenIDAttribute
には属性の型と返された値(値を複数持つ属性の場合は複数の値)が含まれます。SecurityContextHolder
クラスの詳しい使い方についてはtechnical overviewのSpring Securityコアコンポーネントを参照してください。複数のidentity providersを使いたい場合向けに、複数のattribute exchange configurationsもサポートしています。identifier-matcher
属性を使用して複数のattribute-exchange
要素を指定できます。これにはユーザが指定するOpenID identifierにマッチする正規表現が含まれます。設定サンプルとしてはOpenIDサンプルアプリケーションの、Google, Yahoo, MyOpenIDプロバイダそれぞれで異なる属性リストを使っているのを参照してください。
6.3.5 Response Headers
ヘッダー要素のカスタマイズ方法の詳細についてはChapter 20, Security HTTP Response Headersを参照してください。
6.3.6 Adding in Your Own Filters
以前からSpring Securityを使用していれば、このフレームワークは各種サービスを適用するためのフィルターのチェーンがあるのを知っていることかとおもいます。場合によっては、このフィルタースタックの特定位置に自前のフィルタを追加したり、現行のnamespace configurationオプションには存在しない(例えばCAS)Spring Securityのフィルタを使いたい、ことがあります。また、標準のnamespaceフィルタのカスタマイズ版を使用したい場合もあります。たとえば、<form-login>
要素で生成されるUsernamePasswordAuthenticationFilter
などで、このbeanを明示的に設定することで利用可能となるオプションを使いたい場合などです。フィルターチェーンが直接的に公開されていないので、namespace configurationでこれを実現する方法はあるのでしょうか?
フィルタの順序はnamespaceを使う場合では常に厳密なものが強制されています。アプリケーションコンテキストが生成されるとき、フィルターのbeanはnamespaceが処理するコードでソートされ、標準Spring Securityフィルタはそれぞれnamespaceでエイリアスとwell-knownのポジションを持ちます。
以前のバージョンでは、ソートはフィルタインスタンスが生成されたのち、アプリケーションコンテキストのpost-processing中に実行されていました。version 3.0+では、ソートは、クラスがインスタンス化される前の、bean metadata levelで行われます。この点については、<http>
要素のパース中にフィルタリスト全体が明確になる必要があるため、スタックに自前のフィルタを追加する方法に影響を与えます。よって、このシンタックスは3.0で小規模な変更が行われています。
Table 6.1. Standard Filter Aliases and Ordering
Table 6.1, “Standard Filter Aliases and Ordering”は、フィルタを生成するエイリアスとnamespace要素/属性、フィルタのリストです。以下のリストはフィルタチェーンの順になっています。
Alias | Filter Class | Namespace Element or Attribute |
---|---|---|
CHANNEL_FILTER | ChannelProcessingFilter | http/intercept-url@requires-channel |
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 Subclasses | N/A |
CAS_FILTER | CasAuthenticationFilter | N/A |
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 | N/A |
上のスタックに自前のフィルタを追加可能で、custom-filter
要素を使用して追加するフィルタの位置には上のリストの一つを指定します。
<http> <custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" /> </http> <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
after
もしくはbefore
属性も使用可能で、スタックのフィルタの前後どちらかに追加したい場合に使います。スタックの一番前か後ろにフィルタを置きたい場合はposition
属性に"FIRST"もしくは"LAST"をそれぞれ使います。
namespaceで生成される標準フィルタと同一ポジションにカスタムフィルタを追加する場合、誤ってnamecepaceバージョンを含めないことが重要です。置き換えたい機能を持つフィルタを生成する要素を削除してください。なお、<http>
要素の使用により生成されるフィルタ、SecurityContextPersistenceFilter
, ExceptionTranslationFilter
, FilterSecurityInterceptor
は置き換えられません。他いくつかのフィルタがデフォルト追加されますが、これらは無効化できます。session-fixation protectionを無効化しない限りデフォルトでAnonymousAuthenticationFilter
が追加され、フィルターチェーンにSessionManagementFilter
が追加されます。
authentication entry point(例:セキュアなリソースに未認証のユーザがアクセスを試みた場合にトリガされる認証プロセス)を必要とするnamespaceフィルタを置き換える場合、custom entry point beanも追加する必要があります。
Setting a Custom AuthenticationEntryPoint
フォームログインを使わない場合、namespaceではOpenIDやベーシック認証などで、認証フィルターと伝統的なbeanシンタックスでエントリーポイントを定義、namaspaceでそれらをリンクさせたい場合があると思います。<http>
要素のentry-point-ref
でAuthenticationEntryPoint
を設定します。
CASサンプルアプリケーションがそのシンタックスを使用してnamespaceでカスタムbeanを使用している一例となっています。認証エントリーポイントについて知りたい場合、technical overviewを参照してください。
6.4 Method Security
バージョン2.0以降Spring Securityはサービスレイヤーのメソッドにセキュリティを付加する機能を大幅に強化しています。フレームワーク固有の@Secured
と共にJSR-250アノテーションをサポートしています。また、3.0以降では新たにexpression-based annotationsを使用可能です。bean宣言のデコレートにはintercept-methods
要素で単一のbaenにセキュリティを適用するか、AspectJスタイルのポイントカットでサービスレイヤー全体の複数beanをセキュアにできます。
6.4.1 The <global-method-security> Element
この要素は(要素に適切な属性を設定することで)アプリケーションでアノテーションベースのセキュリティを有効化するために使われ、また、アプリケーションコンテキスト全体に適用されるセキュリティポイントカット宣言をグループ化します。<global-method-security>
要素は一つだけ宣言します。以下の宣言はSpring Securityの@Secured
サポートを有効化します。
<global-method-security secured-annotations="enabled" />
(クラスあるいはインタフェースの)メソッドにアノテーションを追加すると、内容に応じてそのメソッドへのアクセスが制限されます。Spring Security固有のアノテーションはメソッドに属性を定義します。それらの属性はAccessDecisionManager
に渡されてアクセス判定に使われます。
public interface BankService { @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account readAccount(Long id); @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account[] findAccounts(); @Secured("ROLE_TELLER") public Account post(Account account, double amount); }
JSR-250アノテーションを有効化するには以下にします。
<global-method-security jsr250-annotations="enabled" />
上記は標準アノテーションでシンプルなロースベース制約を適用可能できますが、Spring Security固有アノテーションの強力な機能がありません。新しい式ベースシンタックス(expression-based syntax)を使うには以下のようにします。
<global-method-security pre-post-annotations="enabled" />
同等なJavaコードは以下となります。
public interface BankService { @PreAuthorize("isAnonymous()") public Account readAccount(Long id); @PreAuthorize("isAnonymous()") public Account[] findAccounts(); @PreAuthorize("hasAuthority('ROLE_TELLER')") public Account post(Account account, double amount); }
式ベースアノテーションを採用するのが良い場合は、ユーザのオーソリティーリストに対してロール名をチェックする以上の、単純なルール定義が必要な時です。
アノテーションを付与するメソッドは(method-securityが有効化された同一のアプリケーションコンテキスト内の)Spring beanとして定義されたインスタンスの場合にだけセキュアになります。Springで生成していない(new
など)インスタンスをセキュアにしたい場合はAspectJを使う必要があります。
アプリケーションで複数種類のアノテーションを有効化可能ですが、インタフェースやクラスには一種類のみ使用すべきで、これはその場合の振る舞いが未定義なためです。ある特定のメソッドに適用されるアノテーションが二つある場合、一つだけが適用されます。
Adding Security Pointcuts using protect-pointcut
protect-pointcut
はとりわけ強力な機能で、一つの宣言だけで複数のbaenをセキュアにできます。
<global-method-security> <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))" access="ROLE_USER"/> </global-method-security>
上の例は、アプリケーションコンテキストのcom.mycompany
パッケージで"Service"で終わるクラス名のbaenのすべてのメソッドをセキュアにします。ROLE_USER
ロールを持つユーザのみメソッドを呼び出せます。URLマッチング同様、最も広くマッチするものをポイントカットのリストの最初に持ってくる必要があり、これは最初にマッチする式が使われるためです。Securityアノテーションはポイントカットに優先します。
6.5 The Default AccessDecisionManager
このセクションはSpring Security内におけるアクセス制御アーキテクチャ基盤の知識をいくらか必要です。知識を持ち合わせていなければスキップして後で戻ってくれば良く、その理由は、単純なロールベースセキュリティ以上のものを使うカスタマイズを必要とする開発者にのみ関連するセクションなためです。
namespace configurationの場合、AccessDecisionManager
のデフォルトインスタンスが自動的に登録されてメソッド呼び出しとURLアクセスのアクセス決定をするのに使われます。アクセス決定はintercept-url
とprotect-pointcut
宣言(とアノテーションでセキュアにしたメソッドがあればそのアノテーション)で指定するアクセス属性に基づいて行われます。
デフォルトの動作*7はRoleVoter
とAuthenticatedVoter
と共にAffirmativeBased
, AccessDecisionManager
を使用します。これらクラスの詳細についてはauthorizationのチャプターを参照してください。
6.5.1 Customizing the 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>
6.6 The Authentication Manager and the Namespace
Spring Securityの認証サービスを提供するメインのインターフェースはAuthenticationManager
です。このインタフェースは通常Spring SecurityのProviderManager
クラスのインスタンスで、既にフレームワークを使ったことばあれば見たことがあるかもしれません。使ったことがなくても、technical overview chapterで後に解説します。このbeanのインスタンスはauthentication-manager
のnamespace要素を使用して登録されます。namespaceを通してHTTPもしくはメソッドセキュリティのどちらかを使う場合、カスタムのAuthenticationManager
は使えませんが、そこで使われるAuthenticationProvider
経由ですべての制御が可能なので問題にならないと思われます。
ProviderManager
にAuthenticationProvider
beanを追加登録したい場合、<authentication-provider>
要素のref
属性を使用し、この属性値には追加したいプロバイダのbean名を指定します。
<authentication-manager> <authentication-provider ref="casAuthenticationProvider"/> </authentication-manager> <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> ... </bean>
別のよくある使い方としては、コンテキストの別のbeanがAuthenticationManager
の参照を使いたい場合が挙げられます。AuthenticationManager
のエイリアスを登録してアプリケーションコンテキストでそのエイリアス名を使います。
<security:authentication-manager alias="authenticationManager"> ... </security:authentication-manager> <bean id="customizedFormLoginFilter" class="com.somecompany.security.web.CustomFormLoginFilter"> <property name="authenticationManager" ref="authenticationManager"/> ... </bean>
7. Sample Applications
Spring Securityプロジェクトでは利用可能なサンプルアプリケーションがいくつか存在します。大量ダウンロードを避けるため、"tutorial"と"contacts"サンプルのみzipファイルになっています。それ以外はthe introductionにある通りソースから直接ビルドできます。ビルドするのは簡単で詳細はhttp://spring.io/spring-security/のプロジェクトwebサイトにあります。このチャプターで参照するすべてのパスはプロジェクトソースディレクトリに関連するものです。
7.1 Tutorial Sample
チュートリアルのサンプルはとりあえず始めてみるのに適しています。全体的にシンプルなnamespace configurationを使っています。コンパイル済みアプリケーションは配布しているzipファイルに含まれ、webコンテナにデプロイします(spring-security-samples-tutorial-3.1.x.war
)。フォーム認証と、クッキーでログインを自動的に記憶するためのremember-me認証を組み合わせています。
XMLが最小構成でこれを基に修正を加えるのも容易なのでこのチュートリアルサンプルから使い始めることを推奨します。更に、既存アプリケーションにチュートリアルのXMLファイル(とweb.xml
エントリの該当箇所)を追加するのも容易です。これら基本的な連携機能を確認できてから、メソッド認可やドメインオブジェクトセキュリティの追加を試すことを推奨します。
7.2 Contacts
Contacts Sampleは高度な機能のサンプルで、基本的なアプリケーションセキュリティに加えてdomain object access control lists(ACLs)の強力な機能の解説になっています。このアプリケーションではコンタクト(という名の)シンプルなデータベースで管理可能なユーザのインタフェースを提供しています。
デプロイするには、単にSpring Securityで配布しているzipからWARファイルをコンテナのwebapps
ディレクトリにコピーします。warはおおむねspring-security-samples-contacts-3.1.x.war
という名前です(バージョン番号は使用するリリースに依存して変わります)。
コンテナ開始後、アプリケーションがロード出来ているかチェックしてください。http://localhost:8080/contacts がURLです(またはwebコンテナとデプロイしたwarに準じるURL)。
次に、"Debug"をクリックしてください。認証が求められ、そのページに一連のユーザ名とパスワードが表示されます。それを使用して認証すると結果ページに移り、以下のような成功メッセージが表示されます。
Security Debug Information Authentication object is of type: org.springframework.security.authentication.UsernamePasswordAuthenticationToken Authentication object as a String: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@1f127853: Principal: org.springframework.security.core.userdetails.User@b07ed00: Username: rod; \ Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; \ Granted Authorities: ROLE_SUPERVISOR, ROLE_USER; \ Password: [PROTECTED]; Authenticated: true; \ Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: \ RemoteIpAddress: 127.0.0.1; SessionId: 8fkp8t83ohar; \ Granted Authorities: ROLE_SUPERVISOR, ROLE_USER Authentication object holds the following granted authorities: ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR) ROLE_USER (getAuthority(): ROLE_USER) Success! Your web filters appear to be properly configured!
上記のようなメッセージが正常に表示されたのを確認したら、サンプルアプリケーションのホームページに戻り"Manage"をクリックします。アプリケーションを色々試してみてください。注意点としては、現在ログオンしているユーザに利用可能なコンタクトのみ表示され、また、ROLE_SUPERVISOR
を持つユーザのみコンタクトを削除する権限を持っています。これの裏側では、MethodSecurityInterceptor
がビジネスオブジェクトをセキュアにしています。
このアプリケーションではコンタクトそれぞれに関連付けられているaccess control listsを修正できます。これを試してみて、アプリケーションコンテキストXMLファイルを調査することで動作の理解に役立てて下さい。
7.3 LDAP Sample
LDAPサンプルアプリケーションは基本的な設定と、namespace configurationと伝統的なbean使用による同等な設定をセットアップしており、両者は同一のアプリケーションコンテキストファイルにいます。つまり、このアプリケーションには二つの同一な認証プロバイダ設定が存在する、ということです。
7.4 OpenID Sample
OpenIDサンプルではnamespaceでのOpenIDの設定方法と、Google, Yahoo, MyOpenIDアイデンティティ・プロバイダのattribute exchangeの設定方法のデモとなっています(他のプロバイダを追加して試すことも可能)。ユーザフレンドリーなログインページを作るのにJQueryベースのopenid-selectorを使用しており、OpenIDの識別子をイチからタイプせず、プロバイダを簡単に選択できるようにしています。
このアプリケーションは一般的な認証とは異なり、任意のユーザがサイトにアクセス可能です(与えられたOpenID認証が成功すれば)。初回ログイン時には"Welcome [your name]“というメッセージが表示されます。ログアウトして(同一のOpenID識別子で)再度ログインすると"Welcome Back"に変わります。この動作はUserDetailsService
を使用しており、そのカスタム実装ではユーザに標準ロールを割り当てて内部的にmapで識別子を保存します。ここは実際のアプリケーションではデータベースを使うと思われます。詳細はソースを確認してください。また、このクラスは異なるプロバイダから異なる属性が返される点に対応しており、場合に応じたユーザの処理をして氏名を組み立てています。
7.5 CAS Sample
CASサンプルを動かすにはCASサーバとCASクライアント両方が必要です。zip配布ファイルでは無いためthe introductionに書いてるリポジトリからプロジェクトのコードをチェックアウトします。sample/cas
下に関連ファイルがあります。また、Readme.txt
ファイルにサーバとクライアントをソースツリーから直接起動す方法が書いてあります。これらはSSLをサポートします。
7.6 JAAS Sample
JAASサンプルはSpring SecurityでJAAS LoginModuleを使う方法の簡単なサンプルです。ここでのLoginModuleはユーザ名とパスワードが一致すれば認証成功とし、それ以外はLoginExceptionをスローします。サンプルで使われているAuthorityGranterは常にROLE_USERロールを付与します。また、jaas-api-provisionを"true"と設定することでLoginModuleが返すJAAS Subjectとして動作させる方法も含みます。
7.7 Pre-Authentication Sample
このサンプルアプリケーションはJava EEコンテナのログイン情報を使用するようにpre-authenticationフレームワークのbeanをワイヤリングする方法となっています。ユーザ名とロールはコンテナでセットアップします。
コードはsamples/preauth
にあります。
*1:Afterall, if every property was exposed, users could use standard bean configuration.が原文。若干訳に自信が無いがafterallと前の文から、どうせプロパティが全部見えていたって使う場合なんてほとんど無かろう? というニュアンスだと思ったんでこういう訳文にしている。
*2:a normal role-based check should be used.が原文。書いてあるとおりごくごく原始的なロールチェックという意味だが、あんま良い日本語思いつかなかったんで英語のままにしてある。
*3:原文がfootnote~てあるくらいだからなんか記法がバグってるぽいので訳していない。
*4:Spring Security will emit a warning in the log if your login page appears to be secured. が原文。訳せても意味が分からない…
*5:It’s important to realise that these unsecured requests will be completely oblivious to any Spring Security web-related configuration or additional attributes such as requires-channelが原文。oblivious toのあたりの訳がやや自信がない。
*6:so use caution if your code listens for both events.が原文。use cautionで検索すると工事現場の注意表示が引っかかるんだが、イベントをリスナーで受け取るだけだと思うんだが、何に注意せよって言ってるのかが分からん。
*7:default strategyが原文。strategyていつも適当な日本語の名詞に困るものの一つで、戦略だと主語がデカすぎるので、ここではシンプルに「動作」としてみた。