.. _SpringSecurityOverview:

Spring Security概要
================================================================================

.. only:: html

.. contents:: 目次
  :local:

|

| Spring Securityは、アプリケーションにセキュリティ対策機能を実装する際に使用するフレームワークである。 
| Spring Securityはスタンドアロンなアプリケーションでも利用できるが、サーブレットコンテナにデプロイするWebアプリケーションに対してセキュリティ対策を行う際に利用するのが一般的である。
| 本章では、Spring Securityが提供する機能のうち、一般的なWebアプリケーションでの利用頻度が高いと思われる機能にしぼって説明する。

| Spring Securityは、本ガイドラインで紹介していない機能も多く提供している。

| Spring Securityが提供するすべての機能を知りたい場合は、\ :url_spring_security_reference:`Spring Security Reference -Servlet Applications- </servlet/index.html>`\ を参照されたい。

|

.. _SpringSecurityFunctionalities:

Spring Securityの機能
--------------------------------------------------------------------------------

セキュリティ対策の基本機能
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Spring Securityは、セキュリティ対策の基本機能として以下の機能を提供している。

.. tabularcolumns:: |p{0.25\linewidth}|p{0.75\linewidth}|
.. list-table:: \ **セキュリティ対策の基本機能**\
  :header-rows: 1
  :widths: 25 75

  * - 機能
    - 説明
  * - \ :ref:`認証機能<SpringSecurityAuthentication>` \
    - アプリケーションを利用するユーザーの正当性を確認する機能。
  * - \ :ref:`認可機能<SpringSecurityAuthorization>`\
    - アプリケーションが提供するリソースや処理に対してアクセスを制御する機能。

|

セキュリティ対策の強化機能
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Spring Securityでは認証と認可という基本的な機能に加え、Webアプリケーションのセキュリティを強化するための機能をいくつか提供している。

.. tabularcolumns:: |p{0.25\linewidth}|p{0.75\linewidth}|
.. list-table:: \ **セキュリティ対策の強化機能**\
  :header-rows: 1
  :widths: 25 75

  * - 機能
    - 説明
  * - \ :ref:`セッション管理機能<SpringSecuritySessionManagement>`\
    - セッションハイジャック攻撃やセッション固定攻撃からユーザーを守る機能、
      セッションのライフサイクル(生成、破棄、タイムアウト)を制御するための機能。
  * - \ :ref:`CSRF対策機能<SpringSecurityCSRF>`\
    - クロスサイトリクエストフォージェリ(CSRF)攻撃からユーザーを守るための機能。
  * - \ :ref:`セキュリティヘッダ出力機能<SpringSecurityLinkageWithBrowser>`\
    - Webブラウザのセキュリティ対策機能と連携し、ブラウザの機能を悪用した攻撃からユーザーを守るための機能。

|

.. _SpringSecurityArchitecture:

Spring Securityのアーキテクチャ
--------------------------------------------------------------------------------
各機能の詳細な説明を行う前に、Spring Securityのアーキテクチャ概要とSpring Securityを構成する主要なコンポーネントの役割を説明する。

.. note::

  ここで説明する内容は、Spring Securityが提供するデフォルトの動作をそのまま利用する場合や、Spring Securityのコンフィギュレーションをサポートする仕組みを利用する場合は、開発者が直接意識する必要ない。

  そのため、まず各機能の使い方を知りたい場合は、本節を読み飛ばしても問題はない。
    
  ただし、ここで説明する内容は、Spring Securityのデフォルトの動作をカスタマイズする際に必要になるので、アプリケーションのアーキテクトは一読しておくことを推奨する。

|

Spring Securityのモジュール
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

まずフレームワークスタックとなっているSpring Securityの提供モジュールを紹介する。

|

フレームワークスタックモジュール群
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

| フレームワークスタックモジュールは、以下の通りである。
| 本ガイドラインでもこれらのモジュールを使用してセキュリティ対策を行う方法について説明する。

.. tabularcolumns:: |p{0.25\linewidth}|p{0.75\linewidth}|
.. list-table:: \ **フレームワークスタックモジュール群**\
  :header-rows: 1
  :widths: 25 75

  * - モジュール名
    - 説明
  * - \ ``spring-security-core``\
    - 認証と認可機能を実現するために必要となるコアなコンポーネントが格納されている。
      このモジュールに含まれるコンポーネントは、スタンドアロン環境で実行するアプリケーションでも使用することができる。
  * - \ ``spring-security-web``\
    - Webアプリケーションのセキュリティ対策を実現するために必要となるコンポーネントが格納されている。
      このモジュールに含まれるコンポーネントは、Web層(サーブレットAPIなど)に依存する処理を行う。
  * - \ ``spring-security-config``\
    - 各モジュールから提供されているコンポーネントのセットアップをサポートするためのコンポーネント(コンフィギュレーションをサポートするクラスやXMLネームスペースを解析するクラスなど)が格納されている。
      このモジュールを使用すると、Spring Securityのbean定義を簡単に行うことができる。
  * - \ ``spring-security-taglibs``\
    - 認証情報や認可機能にアクセスするためのJSPタグライブラリが格納されている。
  * - \ ``spring-security-acl``\
    - EntityなどのドメインオブジェクトをAccess Control List(ACL)を使用して認可制御するために必要となるコンポーネントが格納されている。
      本モジュールは依存関係の都合上、フレームワークスタックに含まれているモジュールであるため、本ガイドラインにおいて使用方法の説明は行わない。
  * - \ ``thymeleaf-extras-springsecurity6``\
    - 認証情報や認可機能にアクセスするためのThymeleafのダイアレクトが格納されている。

|

要件に合わせて使用するモジュール群
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

| フレームワークスタックではないが、一般的に利用される認証方法などをサポートするために、以下のようなモジュールも提供されている。
| セキュリティ要件に応じて、これらのモジュールの使用も検討されたい。

.. tabularcolumns:: |p{0.25\linewidth}|p{0.75\linewidth}|
.. list-table:: \ **要件に合わせて使用するモジュール群**\
  :header-rows: 1
  :widths: 25 75

  * - モジュール名
    - 説明
  * - \ ``spring-security-remoting``\
    - JNDI経由でDNSにアクセス、Basic認証が必要なWebサイトにアクセス、Spring Securityを使用してセキュリティ対策しているメソッドにRMI経由でアクセスする際に必要となるコンポーネントが格納されている。
  * - \ ``spring-security-aspects``\
    - AspectJを使用してJavaのメソッドに認可機能を適用する際、必要となるコンポーネントが格納されている。
      このモジュールは、AOPとしてSpring AOPを使う場合は不要である。
  * - \ ``spring-security-messaging``\ \ [#fSpringSecurityArchitecture5]_\ 
    - SpringのWeb Socket機能に対してセキュリティ対策を追加するためのコンポーネントが格納されている。 
  * - \ ``spring-security-data``\ \ [#fSpringSecurityArchitecture5]_\ 
    - Spring Dataの機能から認証情報にアクセスできるようにするためのコンポーネントが格納されている。 
  * - \ ``spring-security-ldap``\
    - Lightweight Directory Access Protocol(LDAP)を使用した認証を実現するために必要となるコンポーネントが格納されている。
  * - \ ``spring-security-openid``\
    - OpenID\ [#fSpringSecurityArchitecture1]_\ を使用した認証を実現するために必要となるコンポーネントが格納されている。
  * - \ ``spring-security-cas``\
    - Central Authentication Service(CAS)\ [#fSpringSecurityArchitecture2]_\ と連携するために必要となるコンポーネントが格納されている。
  * - \ ``spring-security-crypto``\
    - 暗号化、キーの生成、ハッシュアルゴリズムを利用したパスワードエンコーディングを行うためのコンポーネントが格納されている。
      このモジュールに含まれるクラスは、フレームワークスタックモジュールである\ ``spring-security-core``\ にも含まれている。

|

テスト用のモジュール
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

Spring Security 4.0からはテストを支援するためのモジュールが追加されている。

.. tabularcolumns:: |p{0.25\linewidth}|p{0.75\linewidth}| 
.. list-table:: \ **テスト用のモジュール** \
  :header-rows: 1 
  :widths: 25 75 
  
  * - モジュール名 
    - 説明 
  * - \ ``spring-security-test``\ \ [#fSpringSecurityArchitecture5]_\ 
    - | Spring Securityに依存しているクラスのテストを支援するためのコンポーネントが格納されている。 
      | このモジュールを使用すると、JUnitテスト時に必要となる認証情報を簡単にセットアップすることができる。 
      | また、Spring MVCのテスト用コンポーネント(\ ``MockMvc``\ )と連携して使用するコンポーネントも含まれている。 

|

.. [#fSpringSecurityArchitecture1] OpenIDは、簡単に言うと「1つのIDで複数のサイトにログインできるようにする」ための仕組みである。
.. [#fSpringSecurityArchitecture2] CASは、OSSとして提供されているシングルサインオン用のサーバーコンポーネントである。詳細は https://www.apereo.org/projects/cas を参照されたい。
.. [#fSpringSecurityArchitecture5] Spring Security 4.0から追加されたモジュールである。

|

.. _SpringSecurityProcess:

フレームワーク処理
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Spring Securityは、サーブレットフィルタの仕組みを使用してWebアプリケーションのセキュリティ対策を行うアーキテクチャを採用しており、以下のような流れで処理を実行している。

.. figure:: ./images_SpringSecurity/Architecture.png
  :width: 100%

  \ **Spring Securityのフレームワークアーキテクチャ**\

.. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
.. list-table::
  :header-rows: 1
  :widths: 10 90

  * - 項番
    - 説明
  * - \ (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アプリケーションから返却されたリソースをクライアントへレスポンスする。

|

| Webアプリケーション向けのフレームワーク処理を構成する主要なコンポーネントは以下の通りである。
| 詳細は\ :url_spring_security_reference:`Spring Security Reference -Servlet Applications:Architecture- </servlet/architecture.html>`\ を参照されたい。
|

FilterChainProxy
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

| \ ``FilterChainProxy``\ クラスは、Webアプリケーション向けのフレームワーク処理のエントリーポイントとなるサーブレットフィルタクラスである。
| このクラスはフレームワーク処理の全体の流れを制御するクラスであり、具体的なセキュリティ対策処理はSecurity Filterに委譲している。
|

HttpFirewall
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

| \ ``HttpFirewall``\ インタフェースは、\ ``HttpServletRequest``\ と\ ``HttpServletResponse``\ に対してファイアウォール機能を組み込むためのインタフェースである。
| デフォルトでは、\ ``StrictHttpFirewall``\ クラスが使用され、ディレクトリトラバーサル攻撃やHTTPレスポンス分割攻撃に対するチェックなどが実装されている。

.. note::

  Spring Security 5.0.1, 4.2.4, 4.1.5より、デフォルトで使用される\ ``HttpFirewall``\ インタフェースの実装クラスは\ ``DefaultHttpFirewall``\ から\ ``StrictHttpFirewall``\ へ変更された。
    
  \ ``DefaultHttpFirewall``\ は\ :url_ietf_rfc:`RFC 2396 </rfc2396.txt>`\ に基づきリクエストURLの正規化を行うことで悪意あるURLを拒否するが、\ ``StrictHttpFirewall``\ はより厳密にURLを構成する文字に不正な値がないことをチェックし、悪意あるURLを拒否する。これにより、認証認可のバイパスやReflected File Download(RFD)攻撃への対策がなされている。
    
  URLの正規化は脆弱性対策としては不十分であるため、従来通り\ ``DefaultHttpFirewall``\ を利用するように変更することは推奨しない。また、\ ``StrictHttpFirewall``\ のチェックについても、一部カスタマイズ可能なパラメータも存在するが、脆弱性の原因となりうるため変更することは推奨しない。
    
  \ ``StrictHttpFirewall``\ の詳細については、\ :url_spring_security_site:`Javadoc </web/firewall/StrictHttpFirewall.html>`\ を参照されたい。

|

.. _SpringSecuritySecurityFilterChain:

SecurityFilterChain
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

\ ``SecurityFilterChain``\ インタフェースは、\ ``FilterChainProxy``\ が受け取ったリクエストに対して、適用するSecurity Filterのリストを管理するためのインタフェースである。
デフォルトでは\ ``DefaultSecurityFilterChain``\ クラスが使用され、適用するSecurity Filterのリストを、リクエストURLのパターン毎に管理する。

たとえば、以下のようなbean定義を行うと、URLに応じて異なる内容のセキュリティ対策を適用することができる。

.. tabs::
  .. group-tab:: Java Config

    * xxx-web/src/main/xxxx/yyyy/zzzz/config/web/SpringSecurityConfig.javaの定義例
    
    .. code-block:: java

      @Bean
      public SecurityFilterChain filterChainApi(HttpSecurity http) throws Exception {
          http.securityMatcher(antMatcher("/api/**")); // (1)
          // omitted
          return http.build();
      }

      @Bean
      public SecurityFilterChain filterChainUi(HttpSecurity http) throws Exception {
          http.securityMatcher(antMatcher("/ui/**"));
          // omitted
          return http.build();
      }
    
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
    
      * - 項番
        - 説明
      * - | (1)
        - | \ ``HttpSecurity#securityMatcher``\ メソッドを呼び出し、SecurityFilterChainを適用するRequestMatcherオブジェクトを指定する。\ ``HttpSecurity#securityMatcher``\ メソッドを呼び出さない場合は、"\ ``/**``\ "がパスパターンとして使用される。
          | 指定可能なパスパターンはRequestMatcherに依存しており、\ :url_multi_blank:`ブランクプロジェクトのデフォルト設定 </parts/JavaConfig-JSP/projectName-web/src/main/java/xxxxxx/yyyyyy/zzzzzz/config/web/SpringSecurityConfig.java#L35>`\ で使用される\ ``AntPathRequestMatcher``\ では\ :url_spring_javadoc:`Ant形式の記述 </org/springframework/util/AntPathMatcher.html>`\ が利用できる。
          | また、RequestMatcherオブジェクトではなくパスパターンを直接指定することも可能であるが、\ ``MvcRequestMatcher``\ が適用されるため、本ガイドラインでは\ ``AntPathRequestMatcher#antMatcher``\ を呼び出して\ ``AntPathRequestMatcher``\ を指定する。詳しくは\ :ref:`パスパターンの解析に利用する仕組みの設定について <SpringSecurityPathPatternJava>`\ を参照されたい。
    
    .. _SpringSecurityPathPatternJava:
    
    .. tip:: \ **パスパターンの解析に利用する仕組みの設定について**\
    
      Spring SecurityはSpring MVCと同時に使用する場合、パス解析にはデフォルトで\ ``MvcRequestMatcher``\ が使用される。ただし、\ ``MvcRequestMatcher``\ を使用するためには\ :url_spring_security_reference:`Spring Securityが案内する方法 </servlet/integrations/mvc.html#mvc-requestmatcher>`\ に従い、Spring MVCとSpring Securityを同一コンテキスト(DIコンテナ)内に設定する必要がある。
      
      \ |framework_name|\では以下のような懸念から\ ``AntPathRequestMatcher``\ (必要に応じて\ ``RegexRequestMatcher``\ )の使用を前提としている。
    
      - \ :ref:`RESTHowToUseApplicationSettingsOfSpringMVC`\ の\ ``SpringMvcRestConfig.java``\ のように、\ ``SpringMvcConfig.java``\ の設定バリエーションを1つのアプリケーション内に複数持つ必要がある場合、\ ``SpringMvcConfig.java``\ に相当するファイルごとにアプリケーションコンテキスト(DIコンテナ)を分け、複数のServletにそれぞれを割り当てる必要があり、 \ ``MvcRequestMatcher``\ を使用できる条件を満たさない。また、設定方法によっては、\ ``MvcRequestMatcher``\ を利用するとSpring MVCと連携せずに動作するという意図しない動作となり、脆弱性に繋がる。
      - \ ``MvcRequestMatcher``\ では、Spring MVCがHandlerMappingやハンドラ(ハンドラメソッド等)を決定する時と同じ処理をパターンマッチングの度に行う(\ ``SpringSecurityConfig.java``\ に記載したpattern毎に実施される)ため、1リクエストあたりの処理コストが増加しやすいと推測される。特に、RESTで使用するパス変数のように、パスの条件にワイルドカードを持つハンドラメソッドを呼び出す際は、「Spring MVCがHandlerMappingやハンドラ(ハンドラメソッド等)を決定する」部分の処理コストがアプリケーションコンテキスト(DIコンテナ)内のハンドラメソッドの定義量に大きく依存するため、アプリケーションコンテキスト(DIコンテナ)を1つにまとめる構造では、性能上の懸念がある。

  .. group-tab:: XML Config

    * xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
    
    .. code-block:: xml
    
        <sec:http pattern="/api/**" request-matcher="ant"> <!-- (1) (2) -->
            <!-- omitted -->
        </sec:http>
    
        <sec:http pattern="/ui/**" request-matcher="ant">
            <!-- omitted -->
        </sec:http>
    
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
    
      * - 項番
        - 説明
      * - | (1)
        - | \ ``pattern``\ 属性を設定し、SecurityFilterChainを適用するパスパターンを指定する。\ ``pattern``\ 属性を指定しない場合は、"\ ``/**``\ "がパスパターンとして使用される。
          | 指定可能なパスパターンはRequestMatcherに依存しており、\ :url_multi_blank:`ブランクプロジェクトのデフォルト設定 </parts/XMLConfig-JSP/projectName-web/src/main/resources/META-INF/spring/spring-security.xml#L9>`\ で使用される\ ``AntPathRequestMatcher``\ では\ :url_spring_javadoc:`Ant形式の記述 </org/springframework/util/AntPathMatcher.html>`\ が利用できる。
          | また、\ ``pattern``\ と\ ``request-matcher``\ の代わりに\ ``request-matcher-ref``\ 属性を設定し、RequestMatcherオブジェクトを直接指定することも可能である。
      * - | (2)
        - | \ ``request-matcher``\ 属性で\ ``ant``\ を指定し、\ ``AntPathRequestMatcher``\ を使用するように設定する。詳しくは\ :ref:`パスパターンの解析に利用する仕組みの設定について <SpringSecurityPathPatternXML>`\ を参照されたい。
    
    .. _SpringSecurityPathPatternXML:
    
    .. tip:: \ **パスパターンの解析に利用する仕組みの設定について**\
    
      Spring SecurityはSpring MVCと同時に使用する場合、パス解析にはデフォルトで\ ``MvcRequestMatcher``\ が使用される。ただし、\ ``MvcRequestMatcher``\ を使用するためには\ :url_spring_security_reference:`Spring Securityが案内する方法 </servlet/integrations/mvc.html#mvc-requestmatcher>`\ に従い、Spring MVCとSpring Securityを同一コンテキスト(DIコンテナ)内に設定する必要がある。
      
      \ |framework_name|\では以下のような懸念から\ ``AntPathRequestMatcher``\ (必要に応じて\ ``RegexRequestMatcher``\ )の使用を前提としている。これに伴い、\ :url_multi_blank:`ブランクプロジェクトのデフォルト設定 </parts/XMLConfig-JSP/projectName-web/src/main/resources/META-INF/spring/spring-security.xml#L9>`\ では\ ``<sec:http>``\ タグに\ ``request-matcher="ant"``\ を設定している。
    
      - \ :ref:`RESTHowToUseApplicationSettingsOfSpringMVC`\ の\ ``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つにまとめる構造では、性能上の懸念がある。

|

Security Filter
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

Security Filterクラスは、フレームワーク機能やセキュリティ対策機能を実現する上で必要となる処理を提供するサーブレットフィルタクラスである。

| Spring Securityは、複数のSecurity Filterを連鎖させることでWebアプリケーションのセキュリティ対策を行う仕組みになっている。
| ここでは、認証と認可機能を実現するために必要となるコアなクラスを紹介する。
| 詳細は \ :url_spring_security_reference:`Spring Security Reference -Security Filters- </servlet/architecture.html#servlet-security-filters>`\ を参照されたい。

.. _SpringSecurityTableSecurityFilter:

.. tabularcolumns:: |p{0.35\linewidth}|p{0.65\linewidth}|
.. list-table:: \ **コアなSecurity Filter**\
  :header-rows: 1
  :widths: 35 65

  * - クラス名
    - 説明
  * - \ ``SecurityContextHolderFilter``\
    - 認証情報についてリクエストを跨いで共有するための処理を提供するクラス。
      
      .. note:: 

        \ :url_spring_security_reference:`Spring Security Reference -Security Filters- </servlet/architecture.html#servlet-security-filters>`\ には記載がないが、Spring Security 5.7.0より非推奨となった\ ``SecurityContextPersistenceFilter``\ の代替クラスである。

  * - \ ``UsernamePasswordAuthenticationFilter``\
    - リクエストパラメータで指定されたユーザー名とパスワードを使用して認証処理を行うクラス。
      \ ``HttpSessionSecurityContextRepository``\ に認証情報を格納することで、リクエストを跨いで認証情報を共有している。
      フォーム認証を行う際に使用する。
  * - \ ``LogoutFilter``\
    - ログアウト処理を行うクラス。
  * - \ ``AuthorizationFilter``\
    - HTTPリクエスト(\ ``HttpServletRequest``\ )に対して認可処理を実行するためのクラス。

      .. warning:: \ **web.xmlの<filter-mapping>には業務要件に応じて適切なDispatcherTypeを設定すること**\

        ブランクプロジェクトのデフォルト設定では、web.xmlの\ ``<filter-mapping>/<dispatcher>``\ には明示的に設定を行っていないため、\ ``REQUEST``\ のみを対象として認可処理が実行される。

        業務要件に応じてweb.xmlの\ ``<filter-mapping>/<dispatcher>``\ で\ ``REQUEST``\ + \ ``FORWARD``\ 等、ディスパッチ先でもFilterが動作するように設定するように留意すること。また、\ ``REQUEST``\ 以外を設定する場合、\ ``REQUEST``\ も含めて動作することを期待する場合は、\ ``REQUEST``\ も含めて設定する必要があることに注意すること。

  * - \ ``ExceptionTranslationFilter``\
    - | \ ``AuthorizationFilter``\ で発生した例外をハンドリングし、クライアントへ返却するレスポンスを制御するクラス。
      | デフォルトの実装では、未認証ユーザーからのアクセスの場合は認証を促すレスポンス、認証済みのユーザーからのアクセスの場合は認可エラーを通知するレスポンスを返却する。

|

.. _SpringSecuritySetup:

Spring Securityのセットアップ
--------------------------------------------------------------------------------

WebアプリケーションにSpring Securityを適用するためのセットアップ方法について説明する。

| ここでは、WebアプリケーションにSpring Securityを適用し、Spring Securityが提供しているデフォルトのログイン画面を表示させる最もシンプルなセットアップ方法を説明する。
| 実際のアプリケーション開発で必要となるカスタマイズ方法や拡張方法については、次節以降で順次説明する。

.. note::

  開発プロジェクトを\ :url_multi_blank:`ブランクプロジェクト <>`\ から作成すると、ここで説明する各設定はセットアップ済みの状態になっている。

  開発プロジェクトの作成方法については、「\ :doc:`../ImplementationAtEachLayer/BlankProject`\ 」を参照されたい。

|

.. _SpringSecuritySetupDependency:

依存ライブラリの適用
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

| まず、Spring Securityを依存関係として使用している共通ライブラリを適用する。
| Spring Securityと共通ライブラリの関連については、\ :ref:`frameworkstack_common_library`\ を参照されたい。

本ガイドラインでは、Mavenを使って開発プロジェクトを作成していることを前提とする。

.. tabs::
  .. group-tab:: JSP

    * xxx-domain/pom.xmlの設定例

    .. code-block:: xml

      <dependency>
          <groupId>org.terasoluna.gfw</groupId>
          <artifactId>terasoluna-gfw-security-core</artifactId>  <!-- (1) -->
      </dependency>

    * xxx-web/pom.xmlの設定例

    .. code-block:: xml

      <dependency>
          <groupId>org.terasoluna.gfw</groupId>
          <artifactId>terasoluna-gfw-security-web</artifactId>  <!-- (2) -->
      </dependency>

    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90

      * - 項番
        - 説明
      * - \ (1)
        - ドメイン層のプロジェクトでSpring Securityの機能を使用する場合は、terasoluna-gfw-security-coreをdependencyに追加する。
      * - \ (2)
        - アプリケーション層のプロジェクトでSpring Securityの機能を使用する場合は、terasoluna-gfw-security-webをdependencyに追加する。

  .. group-tab:: Thymeleaf

    * xxx-domain/pom.xmlの設定例

    .. code-block:: xml

      <dependency>
          <groupId>org.terasoluna.gfw</groupId>
          <artifactId>terasoluna-gfw-security-core</artifactId>  <!-- (1) -->
      </dependency>

    * xxx-web/pom.xmlの設定例

    .. code-block:: 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>

    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90

      * - 項番
        - 説明
      * - \ (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に追加する。

|

bean定義ファイルの作成
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Spring Securityのコンポーネントをbean定義するため、以下のようなXMLファイルを作成する。（\ :url_multi_blank:`ブランクプロジェクト <>`\ より抜粋）

.. tabs::
  .. group-tab:: Java Config

      * xxx-web/src/main/xxxx/yyyy/zzzz/config/web/SpringSecurityConfig.javaの定義例
      
      .. code-block:: java

        @Configuration
        @EnableWebSecurity // (10)
        public class SpringSecurityConfig {
        
            // (2)
            @Bean
            public WebSecurityCustomizer webSecurityCustomizer() {
                return web -> web.ignoring().requestMatchers(antMatcher("/resources/**"));
            }
        
            // (3)
            @Bean
            public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
                http.formLogin(Customizer.withDefaults()); // (4)
                http.logout(Customizer.withDefaults()); // (5)
                http.exceptionHandling(ex -> ex
                        .accessDeniedHandler(accessDeniedHandler())); // (6)
                http.addFilterAfter(
                        userIdMDCPutFilter(), AnonymousAuthenticationFilter.class); // (7)
                http.sessionManagement(Customizer.withDefaults()); // (8)
        
                return http.build();
            }
        
            // (11)
            @Bean("accessDeniedHandler")
            public AccessDeniedHandler accessDeniedHandler() {
                LinkedHashMap<Class<? extends AccessDeniedException>, AccessDeniedHandler> errorHandlers = new LinkedHashMap<>();
        
                AccessDeniedHandlerImpl invalidCsrfTokenErrorHandler = new AccessDeniedHandlerImpl();
                invalidCsrfTokenErrorHandler.setErrorPage("/WEB-INF/views/common/error/invalidCsrfTokenError.jsp");
                errorHandlers.put(InvalidCsrfTokenException.class, invalidCsrfTokenErrorHandler);
        
                AccessDeniedHandlerImpl missingCsrfTokenErrorHandler = new AccessDeniedHandlerImpl();
                missingCsrfTokenErrorHandler.setErrorPage("/WEB-INF/views/common/error/missingCsrfTokenError.jsp");
                errorHandlers.put(MissingCsrfTokenException.class, missingCsrfTokenErrorHandler);
        
                AccessDeniedHandlerImpl defaultErrorHandler = new AccessDeniedHandlerImpl();
                defaultErrorHandler.setErrorPage("/WEB-INF/views/common/error/accessDeniedError.jsp");
        
                return new DelegatingAccessDeniedHandler(errorHandlers, defaultErrorHandler);
            }
        
            // (12)
            @Bean("webSecurityExpressionHandler")
            public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
                return new DefaultWebSecurityExpressionHandler();
            }
        
            // (13)
            @Bean("userIdMDCPutFilter")
            public UserIdMDCPutFilter userIdMDCPutFilter() {
                return new UserIdMDCPutFilter();
            }
        }
      
      .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
      .. list-table::
        :header-rows: 1
        :widths: 10 90
      
        * - 項番
          - 説明
        * - | (2)
          - | \ ``WebSecurityCustomizer``\ をBean定義し、セキュリティ対策が不要なリソースパスの設定を行う。
            | 詳細は\ :ref:`SpringSecurityNotApply`\ を参照されたい。
        * - | (3)
          - | \ ``SecurityFilterChain``\ をBean定義する。
        * - | (4)
          - | \ ``HttpSecurity#formLogin``\ を実装し、フォーム認証を使用したログインに関する設定を行う。
            | 詳細は\ :ref:`form-login`\ を参照されたい。
        * - | (5)
          - | \ ``HttpSecurity#logout``\ を実装し、ログアウトに関する設定を行う。
            | 詳細は\ :ref:`SpringSecurityAuthenticationLogout`\ を参照されたい。
        * - | (6)
          - | \ ``HttpSecurity#exceptionHandling``\ を実装し、アクセスエラー時の制御を行うための設定を定義する。
            | 詳細は\ :ref:`SpringSecurityAuthorizationAccessDeniedHandler`\ 、\ :ref:`SpringSecurityAuthorizationOnError`\ を参照されたい。
        * - | (7)
          - | ログ出力するユーザ情報をMDCに格納するための共通ライブラリのフィルタを定義する。
        * - | (8)
          - | \ ``HttpSecurity#sessionManagement``\ タグ を定義し、セッション管理に関する設定を行う。
            | 詳細は\ :ref:`SpringSecuritySessionManagement`\ を参照されたい。
        * - | (10)
          - | \ ``@EnableWebSecurity``\ アノテーションを設定して、認証機能用のコンポーネントをbean定義する。このアノテーションを定義しておかないとサーバ起動時にエラーが発生する。
        * - | (11)
          - | アクセスエラー時のエラーハンドリングを行うコンポーネントをbean定義する。
        * - | (12)
          - | 画面項目で認可処理を行うハンドラをbean定義する。
        * - | (13)
          - | ログ出力するユーザ情報をMDCにする共通ライブラリのコンポーネントをbean定義する。

    .. tabs::
      .. group-tab:: Thymeleaf
    
        * xxx-web/src/main/xxxx/yyyy/zzzz/config/web/SpringMvcConfig.javaの定義例（抜粋）
    
        .. code-block:: java

          @Bean("templateEngine")
          public SpringTemplateEngine templateEngine() {
              SpringTemplateEngine bean = new SpringTemplateEngine();
              bean.setEnableSpringELCompiler(true);
              bean.setTemplateResolver(templateResolver());
              Set<IDialect> set = new HashSet<>();
              set.add(new SpringSecurityDialect()); // (1)
              bean.setAdditionalDialects(set);
              return bean;
          }
    
        .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
        .. list-table::
            :header-rows: 1
            :widths: 10 90
    
            * - 項番
              - 説明
            * - \ (1)
              - TemplateEngineに、\ ``thymeleaf-extras-springsecurity6``\ が提供するダイアレクト(\ ``SpringSecurityDialect``\ ) を利用する定義を追加する。

  .. group-tab:: XML Config

      * xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
      
      .. code-block:: 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>
      
      .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
      .. list-table::
        :header-rows: 1
        :widths: 10 90
      
        * - 項番
          - 説明
        * - | (1)
          - | Spring Securityから提供されているXMLネームスペースを有効にする。上記例では、\ ``sec``\ という名前を割り当てている。XMLネームスペースを使用すると、Spring Securityのコンポーネントのbean定義を簡単に行うことができる。
        * - | (2)
          - | \ ``<sec:http>``\ タグを定義し、セキュリティ対策が不要なリソースパスの設定を行う。
            | 詳細は\ :ref:`SpringSecurityNotApply`\ を参照されたい。
        * - | (3)
          - | \ ``<sec:http>``\ タグを定義する。\ ``<sec:http>``\ タグを定義すると、Spring Securityを利用するために必要となるコンポーネントのbean定義が自動的に行われる。
        * - | (4)
          - | \ ``<sec:form-login>``\ タグを定義し、フォーム認証を使用したログインに関する設定を行う。
            | 詳細は\ :ref:`form-login`\ を参照されたい。
        * - | (5)
          - | \ ``<sec:logout>``\ タグ を定義し、ログアウトに関する設定を行う。
            | 詳細は\ :ref:`SpringSecurityAuthenticationLogout`\ を参照されたい。
        * - | (6)
          - | \ ``<sec:access-denied-handler>``\ タグを定義し、アクセスエラー時の制御を行うための設定を定義する。
            | 詳細は\ :ref:`SpringSecurityAuthorizationAccessDeniedHandler`\ 、\ :ref:`SpringSecurityAuthorizationOnError`\ を参照されたい。
        * - | (7)
          - | ログ出力するユーザ情報をMDCに格納するための共通ライブラリのフィルタを定義する。
        * - | (8)
          - | \ ``<sec:session-management>``\ タグ を定義し、セッション管理に関する設定を行う。
            | 詳細は\ :ref:`SpringSecuritySessionManagement`\ を参照されたい。
        * - | (9)
          - | \ ``<sec:intercept-url>``\ タグを定義して、すべてのパスに対し認可を\ ``true``\ に設定している。
      
            .. warning:: 
      
              \ ``permitAll``\ を設定しているため、すべてのリクエストが有効になっている。
              
              業務要件に応じ適切に設定を変更されたい。
      
        * - | (10)
          - | \ ``<sec:authentication-manager>``\ タグを定義して、認証機能用のコンポーネントをbean定義する。このタグを定義しておかないとサーバ起動時にエラーが発生する。
        * - | (11)
          - | アクセスエラー時のエラーハンドリングを行うコンポーネントをbean定義する。
        * - | (12)
          - | 画面項目で認可処理を行うハンドラをbean定義する。
        * - | (13)
          - | ログ出力するユーザ情報をMDCにする共通ライブラリのコンポーネントをbean定義する。

    .. tabs::
      .. group-tab:: Thymeleaf
    
        * xxx-web/src/main/resources/META-INF/spring/spring-mvc.xmlの定義例（抜粋）
    
        .. code-block:: 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.springsecurity6.dialect.SpringSecurityDialect" /> <!-- (1) -->
                </set>
              </property>
            </bean>
    
        .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
        .. list-table::
            :header-rows: 1
            :widths: 10 90
    
            * - 項番
              - 説明
            * - \ (1)
              - TemplateEngineに、\ ``thymeleaf-extras-springsecurity6``\ が提供するダイアレクト(\ ``SpringSecurityDialect``\ ) を利用する定義を追加する。

|

作成したbean定義ファイルを使用してSpringのDIコンテナを生成するように定義する。

.. tabs::
  .. group-tab:: Java Config

    * xxx-web/src/main/webapp/WEB-INF/web.xmlの設定例
    
    .. code-block:: xml
    
      <!-- (1) -->
      <listener>
          <listener-class>
              org.springframework.web.context.ContextLoaderListener
          </listener-class>
      </listener>
      <!-- (2) -->
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>
              xxxx.yyyy.zzzz.config.app.ApplicationContextConfig
              xxxx.yyyy.zzzz.config.web.SpringSecurityConfig
          </param-value>
      </context-param>
    
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
    
      * - 項番
        - 説明
      * - \(1)
        -  サーブレットコンテナのリスナクラスとして、\ ``ContextLoaderListener``\ クラスを指定する。
      * - \(2)
        -  サーブレットコンテナの\ ``contextConfigLocation``\ パラメータに、\ ``ApplicationContextConfig.java``\ に加えて、Spring Security用のbean定義クラスを追加する。

  .. group-tab:: XML Config

    * xxx-web/src/main/webapp/WEB-INF/web.xmlの設定例
    
    .. code-block:: 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>
    
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
    
      * - 項番
        - 説明
      * - \(1)
        -  サーブレットコンテナのリスナクラスとして、\ ``ContextLoaderListener``\ クラスを指定する。
      * - \(2)
        -  サーブレットコンテナの\ ``contextConfigLocation``\ パラメータに、\ ``applicationContext.xml``\ に加えて、Spring Security用のbean定義ファイルを追加する。

|

サーブレットフィルタの設定
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
最後に、Spring Securityが提供しているサーブレットフィルタクラス(\ ``FilterChainProxy``\ ) をサーブレットコンテナに登録する。

* xxx-web/src/main/webapp/WEB-INF/web.xmlの設定例

.. code-block:: 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>

.. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
.. list-table::
  :header-rows: 1
  :widths: 10 90
   
  * - 項番
    - 説明
  * - \ (1)
    - Spring Frameworkから提供されている\ ``DelegatingFilterProxy``\ を使用して、
      SpringのDIコンテナで管理されているbean(\ ``FilterChainProxy``\ )をサーブレットコンテナに登録する。
      サーブレットフィルタの名前には、SpringのDIコンテナで管理されているbeanのbean名(\ ``springSecurityFilterChain``\ )を指定する。
  * - \ (2)
    -  Spring Securityを適用するURLのパターンを指定する。
       上記例では、すべてのリクエストに対してSpring Securityを適用する。

|

.. _SpringSecurityNotApply:

セキュリティ対策を適用しないため設定
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

セキュリティ対策が不要なリソースのパス(cssファイルやimageファイルにアクセスするためのパスなど)に対しては、\ ``WebSecurityCustomizer``\ (または\ ``<sec:http>``\ タグ）を使用して、Spring Securityのセキュリティ機能(Security Filter)が適用されないように制御することができる。

.. tabs::
  .. group-tab:: Java Config

    * xxx-web/src/main/xxxx/yyyy/zzzz/SpringSecurityConfig.javaの定義例
    
    .. code-block:: java

      @Bean
      public WebSecurityCustomizer webSecurityCustomizer() {
          return web -> web.ignoring().requestMatchers(
                  antMatcher("/resources/**")); // (1)(2)
      }

      @Bean
      public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
          // omitted
          return http.build();
      }
      
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
      
      * - 項番
        - 説明
      * - | (1)
        - | \ ``AntPathRequestMatcher#antMatcher``\ にセキュリティ機能を適用しないパスのパターンを指定する。
      * - | (2)
        - | \ ``WebSecurity#ignoring``\ を呼び出し、Spring Securityのセキュリティ機能(Security Filter)が適用されないように設定する。

  .. group-tab:: XML Config

    * xxx-web/src/main/resources/META-INF/spring/spring-security.xmlの定義例
    
    .. code-block:: xml
      
      <sec:http pattern="/resources/**" request-matcher="ant" security="none"/>  <!-- (1) (2) -->
      <sec:http request-matcher="ant">
          <!-- omitted -->
      </sec:http>
      
    .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}|
    .. list-table::
      :header-rows: 1
      :widths: 10 90
      
      * - 項番
        - 説明
      * - | (1)
        - | \ ``pattern``\ 属性にセキュリティ機能を適用しないパスのパターンを指定する。
      * - | (2)
        - | \ ``security``\ 属性に\ ``none``\ を指定する。
          | \ ``none``\ を指定すると、Spring Securityのセキュリティ機能(Security Filter)が適用されない。

.. raw:: latex

   \newpage
