9.1. Spring Security概要¶
目次
9.1.1. Spring Securityの機能¶
9.1.1.1. セキュリティ対策の基本機能¶
Spring Securityは、セキュリティ対策の基本機能として以下の機能を提供している。
機能 | 説明 |
---|---|
認証機能 | アプリケーションを利用するユーザーの正当性を確認する機能。 |
認可機能 | アプリケーションが提供するリソースや処理に対してアクセスを制御する機能。 |
9.1.1.2. セキュリティ対策の強化機能¶
Spring Securityでは認証と認可という基本的な機能に加え、Webアプリケーションのセキュリティを強化するための機能をいくつか提供している。
機能 | 説明 |
---|---|
セッション管理機能 | セッションハイジャック攻撃やセッション固定攻撃からユーザーを守る機能、 セッションのライフサイクル(生成、破棄、タイムアウト)を制御するための機能。 |
CSRF対策機能 | クロスサイトリクエストフォージェリ(CSRF)攻撃からユーザーを守るための機能。 |
セキュリティヘッダ出力機能 | Webブラウザのセキュリティ対策機能と連携し、ブラウザの機能を悪用した攻撃からユーザーを守るための機能。 |
9.1.2. Spring Securityのアーキテクチャ¶
各機能の詳細な説明を行う前に、Spring Securityのアーキテクチャ概要とSpring Securityを構成する主要なコンポーネントの役割を説明する。
Note
ここで説明する内容は、Spring Securityが提供するデフォルトの動作をそのまま利用する場合や、Spring Securityのコンフィギュレーションをサポートする仕組みを利用する場合は、開発者が直接意識する必要ない。
そのため、まず各機能の使い方を知りたい場合は、本節を読み飛ばしても問題はない。
ただし、ここで説明する内容は、Spring Securityのデフォルトの動作をカスタマイズする際に必要になるので、アプリケーションのアーキテクトは一読しておくことを推奨する。
9.1.2.1. Spring Securityのモジュール¶
まずフレームワークスタックとなっているSpring Securityの提供モジュールを紹介する。
9.1.2.1.1. フレームワークスタックモジュール群¶
モジュール名 | 説明 |
---|---|
spring-security-core |
認証と認可機能を実現するために必要となるコアなコンポーネントが格納されている。 このモジュールに含まれるコンポーネントは、スタンドアロン環境で実行するアプリケーションでも使用することができる。 |
spring-security-web |
Webアプリケーションのセキュリティ対策を実現するために必要となるコンポーネントが格納されている。 このモジュールに含まれるコンポーネントは、Web層(サーブレットAPIなど)に依存する処理を行う。 |
spring-security-config |
各モジュールから提供されているコンポーネントのセットアップをサポートするためのコンポーネント(コンフィギュレーションをサポートするクラスやXMLネームスペースを解析するクラスなど)が格納されている。 このモジュールを使用すると、Spring Securityのbean定義を簡単に行うことができる。 |
spring-security-acl |
EntityなどのドメインオブジェクトをAccess Control List(ACL)を使用して認可制御するために必要となるコンポーネントが格納されている。 本モジュールは依存関係の都合上、フレームワークスタックに含まれているモジュールであるため、本ガイドラインにおいて使用方法の説明は行わない。 |
thymeleaf-extras-springsecurity6 |
認証情報や認可機能にアクセスするためのThymeleafのダイアレクトが格納されている。 |
9.1.2.1.2. 要件に合わせて使用するモジュール群¶
モジュール名 | 説明 |
---|---|
spring-security-remoting |
JNDI経由でDNSにアクセス、Basic認証が必要なWebサイトにアクセス、Spring Securityを使用してセキュリティ対策しているメソッドにRMI経由でアクセスする際に必要となるコンポーネントが格納されている。 |
spring-security-aspects |
AspectJを使用してJavaのメソッドに認可機能を適用する際、必要となるコンポーネントが格納されている。 このモジュールは、AOPとしてSpring AOPを使う場合は不要である。 |
spring-security-messaging [3] |
SpringのWeb Socket機能に対してセキュリティ対策を追加するためのコンポーネントが格納されている。 |
spring-security-data [3] |
Spring Dataの機能から認証情報にアクセスできるようにするためのコンポーネントが格納されている。 |
spring-security-ldap |
Lightweight Directory Access Protocol(LDAP)を使用した認証を実現するために必要となるコンポーネントが格納されている。 |
spring-security-openid |
OpenID[1]を使用した認証を実現するために必要となるコンポーネントが格納されている。 |
spring-security-cas |
Central Authentication Service(CAS)[2]と連携するために必要となるコンポーネントが格納されている。 |
spring-security-crypto |
暗号化、キーの生成、ハッシュアルゴリズムを利用したパスワードエンコーディングを行うためのコンポーネントが格納されている。
このモジュールに含まれるクラスは、フレームワークスタックモジュールであるspring-security-core にも含まれている。 |
9.1.2.1.3. テスト用のモジュール¶
Spring Security 4.0からはテストを支援するためのモジュールが追加されている。
モジュール名 | 説明 |
---|---|
spring-security-test [3] |
Spring Securityに依存しているクラスのテストを支援するためのコンポーネントが格納されている。
このモジュールを使用すると、JUnitテスト時に必要となる認証情報を簡単にセットアップすることができる。
また、Spring MVCのテスト用コンポーネント(
MockMvc )と連携して使用するコンポーネントも含まれている。 |
[1] | OpenIDは、簡単に言うと「1つのIDで複数のサイトにログインできるようにする」ための仕組みである。 |
[2] | CASは、OSSとして提供されているシングルサインオン用のサーバーコンポーネントである。詳細は https://www.apereo.org/projects/cas を参照されたい。 |
[3] | (1, 2, 3) Spring Security 4.0から追加されたモジュールである。 |
9.1.2.2. フレームワーク処理¶
Spring Securityは、サーブレットフィルタの仕組みを使用してWebアプリケーションのセキュリティ対策を行うアーキテクチャを採用しており、以下のような流れで処理を実行している。
項番 | 説明 |
---|---|
(1) | クライアントは、Webアプリケーションに対してリクエストを送る。 |
(2) | Spring SecurityのFilterChainProxy クラス(サーブレットフィルタ)がリクエストを受け取り、
HttpFirewall インタフェースのメソッドを呼び出してHttpServletRequest とHttpServletResponse に対してファイアウォール機能を組み込む。 |
(3) | FilterChainProxy クラスは、Spring Securityが提供しているセキュリティ対策用のSecurity Filter(サーブレットフィルタ)クラスに処理を委譲する。 |
(4) | Security Filterは複数のクラスで構成されており、サーブレットフィルタの処理が正常に終了すると後続のサーブレットフィルタが呼び出される。 |
(5) | 最後のSecurity Filterの処理が正常に終了した場合、後続処理(サーブレットフィルタやサーブレットなど)を呼びだし、Webアプリケーション内のリソースへアクセスする。 |
(6) | FilterChainProxy クラスは、Webアプリケーションから返却されたリソースをクライアントへレスポンスする。 |
9.1.2.2.1. FilterChainProxy¶
FilterChainProxy
クラスは、Webアプリケーション向けのフレームワーク処理のエントリーポイントとなるサーブレットフィルタクラスである。9.1.2.2.2. HttpFirewall¶
HttpFirewall
インタフェースは、HttpServletRequest
とHttpServletResponse
に対してファイアウォール機能を組み込むためのインタフェースである。StrictHttpFirewall
クラスが使用され、ディレクトリトラバーサル攻撃やHTTPレスポンス分割攻撃に対するチェックなどが実装されている。Note
Spring Security 5.0.1, 4.2.4, 4.1.5より、デフォルトで使用されるHttpFirewall
インタフェースの実装クラスはDefaultHttpFirewall
からStrictHttpFirewall
へ変更された。
DefaultHttpFirewall
はRFC 2396に基づきリクエストURLの正規化を行うことで悪意あるURLを拒否するが、StrictHttpFirewall
はより厳密にURLを構成する文字に不正な値がないことをチェックし、悪意あるURLを拒否する。これにより、認証認可のバイパスやReflected File Download(RFD)攻撃への対策がなされている。
URLの正規化は脆弱性対策としては不十分であるため、従来通りDefaultHttpFirewall
を利用するように変更することは推奨しない。また、StrictHttpFirewall
のチェックについても、一部カスタマイズ可能なパラメータも存在するが、脆弱性の原因となりうるため変更することは推奨しない。
StrictHttpFirewall
の詳細については、Javadocを参照されたい。
9.1.2.2.3. SecurityFilterChain¶
SecurityFilterChain
インタフェースは、FilterChainProxy
が受け取ったリクエストに対して、適用するSecurity Filterのリストを管理するためのインタフェースである。
デフォルトではDefaultSecurityFilterChain
クラスが使用され、適用するSecurity Filterのリストを、リクエストURLのパターン毎に管理する。
たとえば、以下のようなbean定義を行うと、URLに応じて異なる内容のセキュリティ対策を適用することができる。
- xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
<sec:http pattern="/api/**" request-matcher="ant"> <!-- (1) (2) -->
<!-- omitted -->
</sec:http>
<sec:http pattern="/ui/**" request-matcher="ant">
<!-- omitted -->
</sec:http>
項番 | 説明 |
---|---|
(1)
|
pattern 属性を設定し、SecurityFilterChainを適用するパスパターンを指定する。pattern 属性を指定しない場合は、”/** ”がパスパターンとして使用される。また、
pattern とrequest-matcher の代わりにrequest-matcher-ref 属性を設定し、RequestMatcherオブジェクトを直接指定することも可能である。 |
(2)
|
Tip
パスパターンの解析に利用する仕組みの設定について
Spring SecurityはSpring MVCと同時に使用する場合、パス解析にはデフォルトでMvcRequestMatcher
が使用される。ただし、MvcRequestMatcher
を使用するためにはSpring Securityが案内する方法に従い、Spring MVCとSpring Securityを同一コンテキスト(DIコンテナ)内に設定する必要がある。
Macchinetta Server Framework (1.x)では以下のような懸念からAntPathRequestMatcher
(必要に応じてRegexRequestMatcher
)の使用を前提としている。これに伴い、ブランクプロジェクトのデフォルト設定では<sec:http>
タグにrequest-matcher="ant"
を設定している。
- RESTful Web Serviceで必要となるSpring MVCのコンポーネントを有効化するための設定の
spring-mvc-rest.xml
のように、spring-mvc.xml
の設定バリエーションを1つのアプリケーション内に複数持つ必要がある場合、spring-mvc.xml
に相当するファイルごとにアプリケーションコンテキスト(DIコンテナ)を分け、複数のServletにそれぞれを割り当てる必要があり、MvcRequestMatcher
を使用できる条件を満たさない。また、設定方法によっては、MvcRequestMatcher
を利用するとSpring MVCと連携せずに動作するという意図しない動作となり、脆弱性に繋がる。 MvcRequestMatcher
では、Spring MVCがHandlerMappingやハンドラ(ハンドラメソッド等)を決定する時と同じ処理をパターンマッチングの度に行う(spring-security.xml
に記載したpattern毎に実施される)ため、1リクエストあたりの処理コストが増加しやすいと推測される。特に、RESTで使用するパス変数のように、パスの条件にワイルドカードを持つハンドラメソッドを呼び出す際は、「Spring MVCがHandlerMappingやハンドラ(ハンドラメソッド等)を決定する」部分の処理コストがアプリケーションコンテキスト(DIコンテナ)内のハンドラメソッドの定義量に大きく依存するため、アプリケーションコンテキスト(DIコンテナ)を1つにまとめる構造では、性能上の懸念がある。
9.1.2.2.4. Security Filter¶
Security Filterクラスは、フレームワーク機能やセキュリティ対策機能を実現する上で必要となる処理を提供するサーブレットフィルタクラスである。
クラス名 | 説明 |
---|---|
SecurityContextHolderFilter |
認証情報についてリクエストを跨いで共有するための処理を提供するクラス。 Note Spring Security Reference -Security Filters-には記載がないが、
Spring Security 5.7.0より非推奨となった |
UsernamePasswordAuthenticationFilter |
リクエストパラメータで指定されたユーザー名とパスワードを使用して認証処理を行うクラス。
HttpSessionSecurityContextRepository に認証情報を格納することで、リクエストを跨いで認証情報を共有している。
フォーム認証を行う際に使用する。 |
LogoutFilter |
ログアウト処理を行うクラス。 |
AuthorizationFilter |
HTTPリクエスト( Warning web.xmlの<filter-mapping>には業務要件に応じて適切なDispatcherTypeを設定すること ブランクプロジェクトのデフォルト設定では、web.xmlの 業務要件に応じてweb.xmlの |
ExceptionTranslationFilter |
AuthorizationFilter で発生した例外をハンドリングし、クライアントへ返却するレスポンスを制御するクラス。デフォルトの実装では、未認証ユーザーからのアクセスの場合は認証を促すレスポンス、認証済みのユーザーからのアクセスの場合は認可エラーを通知するレスポンスを返却する。
|
9.1.3. Spring Securityのセットアップ¶
WebアプリケーションにSpring Securityを適用するためのセットアップ方法について説明する。
Note
開発プロジェクトをブランクプロジェクトから作成すると、ここで説明する各設定はセットアップ済みの状態になっている。
開発プロジェクトの作成方法については、「Webアプリケーション向け開発プロジェクトの作成」を参照されたい。
9.1.3.1. 依存ライブラリの適用¶
本ガイドラインでは、Mavenを使って開発プロジェクトを作成していることを前提とする。
- xxx-domain/pom.xmlの設定例
<dependency>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-security-core</artifactId> <!-- (1) -->
</dependency>
- xxx-web/pom.xmlの設定例
<dependency>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-security-web</artifactId> <!-- (2) -->
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId> <!-- (3) -->
</dependency>
項番 | 説明 |
---|---|
(1) | ドメイン層のプロジェクトでSpring Securityの機能を使用する場合は、terasoluna-gfw-security-coreをdependencyに追加する。 |
(2) | アプリケーション層のプロジェクトでSpring Securityの機能を使用する場合は、terasoluna-gfw-security-webをdependencyに追加する。 |
(3) | アプリケーション層のプロジェクトでThymeleafのHTMLテンプレートにてSpring Securityの機能を使用する場合は、thymeleaf-extras-springsecurity6をdependencyに追加する。 |
Note
上記設定例は、依存ライブラリのバージョンを親プロジェクトである terasoluna-gfw-parent で管理する前提であるため、pom.xmlでのバージョンの指定は不要である。
9.1.3.2. bean定義ファイルの作成¶
Spring Securityのコンポーネントをbean定義するため、以下のようなXMLファイルを作成する。(ブランクプロジェクトより抜粋)
- xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
"> <!-- (1) -->
<sec:http pattern="/resources/**" request-matcher="ant" security="none"/> <!-- (2) -->
<sec:http request-matcher="ant"> <!-- (3) -->
<sec:form-login /> <!-- (4) -->
<sec:logout /> <!-- (5) -->
<sec:access-denied-handler ref="accessDeniedHandler"/> <!-- (6) -->
<sec:custom-filter ref="userIdMDCPutFilter" after="ANONYMOUS_FILTER"/> <!-- (7) -->
<sec:session-management /> <!-- (8) -->
<sec:intercept-url pattern="/**" access="permitAll" /> <!-- (9) -->
</sec:http>
<sec:authentication-manager /> <!-- (10) -->
<!-- CSRF Protection -->
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.DelegatingAccessDeniedHandler"> <!-- (11) -->
<!-- omitted -->
</bean>
<bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" /> <!-- (12) -->
<!-- Put UserID into MDC -->
<bean id="userIdMDCPutFilter" class="org.terasoluna.gfw.security.web.logging.UserIdMDCPutFilter"> <!-- (13) -->
</bean>
</beans>
項番 | 説明 |
---|---|
(1)
|
Spring Securityから提供されているXMLネームスペースを有効にする。上記例では、
sec という名前を割り当てている。XMLネームスペースを使用すると、Spring Securityのコンポーネントのbean定義を簡単に行うことができる。 |
(2)
|
<sec:http> タグを定義し、セキュリティ対策が不要なリソースパスの設定を行う。詳細はセキュリティ対策を適用しないため設定を参照されたい。
|
(3)
|
<sec:http> タグを定義する。<sec:http> タグを定義すると、Spring Securityを利用するために必要となるコンポーネントのbean定義が自動的に行われる。 |
(4)
|
<sec:form-login> タグを定義し、フォーム認証を使用したログインに関する設定を行う。詳細はフォーム認証を参照されたい。
|
(5)
|
<sec:logout> タグ を定義し、ログアウトに関する設定を行う。詳細はログアウトを参照されたい。
|
(6)
|
<sec:access-denied-handler> タグを定義し、アクセスエラー時の制御を行うための設定を定義する。詳細はAccessDeniedHandlerの適用、認可エラー時の遷移先を参照されたい。
|
(7)
|
ログ出力するユーザ情報をMDCに格納するための共通ライブラリのフィルタを定義する。
|
(8)
|
<sec:session-management> タグ を定義し、セッション管理に関する設定を行う。詳細はセッション管理を参照されたい。
|
(9)
|
<sec:intercept-url> タグを定義して、すべてのパスに対し認可をtrue に設定している。Warning
業務要件に応じ適切に設定を変更されたい。 |
(10)
|
<sec:authentication-manager> タグを定義して、認証機能用のコンポーネントをbean定義する。このタグを定義しておかないとサーバ起動時にエラーが発生する。 |
(11)
|
アクセスエラー時のエラーハンドリングを行うコンポーネントをbean定義する。
|
(12)
|
画面項目で認可処理を行うハンドラをbean定義する。
|
(13)
|
ログ出力するユーザ情報をMDCにする共通ライブラリのコンポーネントをbean定義する。
|
- xxx-web/src/main/resources/META-INF/spring/spring-mvc.xmlの定義例(抜粋)
<bean id="templateEngine" class="org.thymeleaf.spring6.SpringTemplateEngine">
<property name="enableSpringELCompiler" value="true" />
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect" /> <!-- (1) -->
<bean class="org.thymeleaf.extras.java8time.dialect.Java8TimeDialect" />
</set>
</property>
</bean>
項番 | 説明 |
---|---|
(1) | TemplateEngineに、thymeleaf-extras-springsecurity5 が提供するダイアレクト(SpringSecurityDialect ) を利用する定義を追加する。 |
作成したbean定義ファイルを使用してSpringのDIコンテナを生成するように定義する。
- xxx-web/src/main/webapp/WEB-INF/web.xmlの設定例
<!-- (1) -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- (2) -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:META-INF/spring/applicationContext.xml
classpath*:META-INF/spring/spring-security.xml
</param-value>
</context-param>
項番 | 説明 |
---|---|
(1) | サーブレットコンテナのリスナクラスとして、ContextLoaderListener クラスを指定する。 |
(2) | サーブレットコンテナのcontextClass パラメータに、applicationContext.xml に加えて、Spring Security用のbean定義ファイルを追加する。 |
9.1.3.3. サーブレットフィルタの設定¶
最後に、Spring Securityが提供しているサーブレットフィルタクラス(FilterChainProxy
) をサーブレットコンテナに登録する。
- xxx-web/src/main/webapp/WEB-INF/web.xmlの設定例
<!-- (1) -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<!-- (2) -->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
項番 | 説明 |
---|---|
(1) | Spring Frameworkから提供されているDelegatingFilterProxy を使用して、
SpringのDIコンテナで管理されているbean(FilterChainProxy )をサーブレットコンテナに登録する。
サーブレットフィルタの名前には、SpringのDIコンテナで管理されているbeanのbean名(springSecurityFilterChain )を指定する。 |
(2) | Spring Securityを適用するURLのパターンを指定する。 上記例では、すべてのリクエストに対してSpring Securityを適用する。 |
9.1.3.4. セキュリティ対策を適用しないため設定¶
セキュリティ対策が不要なリソースのパス(cssファイルやimageファイルにアクセスするためのパスなど)に対しては、
<sec:http>
タグを使用して、Spring Securityのセキュリティ機能(Security Filter)が適用されないように制御することができる。
- xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
<sec:http pattern="/resources/**" request-matcher="ant" security="none"/> <!-- (1) (2) -->
<sec:http request-matcher="ant">
<!-- omitted -->
</sec:http>
項番 | 説明 |
---|---|
(1)
|
pattern 属性にセキュリティ機能を適用しないパスのパターンを指定する。 |
(2)
|
security 属性にnone を指定する。none を指定すると、Spring Securityのセキュリティ機能(Security Filter)が適用されない。 |