# 機能設計書 21-Security HTTP

## 概要

本ドキュメントは、Symfony Security HTTPコンポーネントの機能設計を記述する。このコンポーネントは、セキュリティコンポーネントのHTTP統合機能を提供し、ファイアウォール、認証リスナー、アクセス制御マップ等を通じてWebアプリケーションのセキュリティを実現する。

### 本機能の処理概要

**業務上の目的・背景**：Webアプリケーションにおいて、HTTPリクエストレベルでのセキュリティ制御は不可欠である。Security HTTPコンポーネントは、HTTPリクエストのライフサイクルにセキュリティ機能を統合し、認証・認可・ログアウト・ユーザー切り替え等の処理をイベント駆動で実現する。これにより、アプリケーション開発者はセキュリティの複雑な処理をフレームワークに委任し、ビジネスロジックに集中できる。

**機能の利用シーン**：全てのHTTPリクエスト処理において利用される。ログインフォーム認証、APIトークン認証、HTTP Basic認証、Remember Me機能、ログアウト処理、アクセス制御（URLパターンベースのロール制限）、ログインスロットリング等、セキュリティに関わるあらゆる場面で動作する。

**主要な処理内容**：
1. Firewallクラスによるリクエストイベントの監視と、FirewallMapに基づくセキュリティリスナーの動的登録
2. Authenticatorインターフェースを通じた多様な認証方式（フォームログイン、JSON認証、HTTP Basic、アクセストークン等）の統一的なサポート
3. AccessMapによるURLパターンベースのアクセス制御ルール管理
4. HttpUtilsによるセキュリティ関連のHTTPリダイレクト・リクエスト生成・URLマッチング
5. EventListenerによるクレデンシャル検証、Remember Me処理、CSRF保護、ログインスロットリング等の横断的関心事の処理
6. ログアウト処理（セッションクリア、Cookie削除、CSRFトークン検証等）

**関連システム・外部連携**：Security Coreコンポーネント（認証トークン、ユーザープロバイダー）、Security CSRFコンポーネント（CSRF保護）、HttpFoundation（リクエスト・レスポンス）、HttpKernel（イベントシステム）、Routing（URL生成・マッチング）と連携する。

**権限による制御**：AccessMapにより、URLパターンごとにアクセスに必要なロール（ROLE_USER、ROLE_ADMIN等）やチャネル（http/https）を設定可能。ファイアウォール設定により、URLパターンごとに異なる認証戦略を適用できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | セキュリティパネル | 補助機能 | ファイアウォール設定、認証リスナーの情報の表示 |

## 機能種別

認証・認可処理 / イベント駆動型セキュリティ統合

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Request | Request | Yes | HTTPリクエストオブジェクト | HttpFoundation Requestインスタンス |
| FirewallMap | FirewallMapInterface | Yes | ファイアウォール設定マップ | RequestMatcherInterfaceとリスナーの組み合わせ |
| EventDispatcher | EventDispatcherInterface | Yes | イベントディスパッチャー | PSR-14準拠のディスパッチャー |

### 入力データソース

HTTPリクエスト（ヘッダー、Cookie、セッション、フォームデータ）、ファイアウォール設定（DI経由）、認証情報（ユーザー名/パスワード、トークン等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Response | Response | 認証成功/失敗時のHTTPレスポンス（リダイレクト等） |
| TokenInterface | TokenInterface | 認証成功時の認証トークン |
| SecurityAttributes | array | リクエスト属性に設定されるセキュリティ関連情報 |

### 出力先

HTTPレスポンス（リダイレクト、403/401エラー等）、セッション（認証トークン保存）、イベントディスパッチャー（セキュリティイベント発火）

## 処理フロー

### 処理シーケンス

```
1. KernelEvents::REQUESTイベント発火（優先度8）
   └─ Firewall::onKernelRequest()が呼び出される
2. FirewallMapからリクエストに一致するリスナーを取得
   └─ RequestMatcherでURLパターンマッチング
3. ExceptionListenerをイベントディスパッチャーに登録
   └─ 認証例外・アクセス拒否例外のハンドリング準備
4. 認証リスナーを順次実行（優先度順）
   └─ 各リスナーのsupports()で対象判定後、authenticate()を実行
5. 認証成功時: トークン生成・保存、成功レスポンス返却
   └─ onAuthenticationSuccess()コールバック
6. 認証失敗時: 例外レスポンス返却
   └─ onAuthenticationFailure()コールバック
7. KernelEvents::FINISH_REQUESTでExceptionListenerを解除
   └─ リスナーのクリーンアップ
```

### フローチャート

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B[Firewall::onKernelRequest]
    B --> C{メインリクエスト?}
    C -->|No| Z[スキップ]
    C -->|Yes| D[FirewallMap::getListeners]
    D --> E[ExceptionListener登録]
    E --> F[認証リスナーループ]
    F --> G{supports?}
    G -->|false| H[次のリスナー]
    G -->|true| I[authenticate実行]
    I --> J{認証成功?}
    J -->|Yes| K[トークン生成・保存]
    J -->|No| L[認証失敗レスポンス]
    K --> M[成功レスポンス]
    H --> F
    M --> N[終了]
    L --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | ファイアウォールマッチング | リクエストURLに一致する最初のファイアウォール設定が適用される | 全HTTPリクエスト |
| BR-21-02 | リスナー優先度 | 認証リスナーはSortFirewallListenersPassで事前ソートされた優先度順に実行される | 認証処理時 |
| BR-21-03 | ドメイン検証 | リダイレクト先URLがdomainRegexpに一致しない場合、'/'にフォールバックする | リダイレクト生成時 |
| BR-21-04 | LogoutListener配置 | LogoutListenerは他のリスナーとの優先度に基づき適切な位置に挿入される | ログアウト設定時 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

直接的なデータベース操作は行わない。セッションストレージ（ファイル、DB等）への間接的な操作はセッションハンドラーに委任される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | AuthenticationException | 認証情報が不正または不足 | ログイン画面へリダイレクトまたは401レスポンス |
| 403 | AccessDeniedException | 認証済みだがアクセス権限不足 | 403レスポンスまたはアクセス拒否ハンドラーで処理 |
| - | LogicException | UrlGeneratorが未設定でルート名指定のリダイレクト | UrlGeneratorInterfaceの設定が必要 |

### リトライ仕様

LoginThrottlingListenerにより、一定回数以上のログイン失敗時にレート制限が適用される。RateLimiterコンポーネントと連携する。

## トランザクション仕様

直接的なトランザクション管理は行わない。セッション操作はPHPのセッション機構に依存する。

## パフォーマンス要件

ファイアウォールマッチングは全リクエストに対して実行されるため、マッチャーの数を最小限に保つことが重要。認証リスナーはsupports()メソッドで早期に対象外判定を行い、不要な処理をスキップする設計となっている。

## セキュリティ考慮事項

- HttpUtilsのリダイレクト生成では、domainRegexpおよびsecureDomainRegexpによるオープンリダイレクト攻撃の防止機能を持つ
- SensitiveParameterアトリビュートによるパスワード等機密情報のスタックトレースからの除外
- セキュリティ属性（AUTHENTICATION_ERROR、ACCESS_DENIED_ERROR等）はリクエスト属性として安全に伝播される
- LoginThrottlingListenerによるブルートフォース攻撃対策

## 備考

Security HTTPコンポーネントはSymfonyセキュリティシステムの中核的なHTTP統合レイヤーであり、Security CoreやSecurity CSRFと密接に連携する。Symfony 7.0以降、Authenticatorベースのセキュリティシステムが標準となっている。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ファイアウォールシステムの基本インターフェースとデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FirewallMapInterface.php | `src/Symfony/Component/Security/Http/FirewallMapInterface.php` | ファイアウォールマップの契約を理解する |
| 1-2 | AccessMapInterface.php | `src/Symfony/Component/Security/Http/AccessMapInterface.php` | アクセス制御マップのインターフェース |
| 1-3 | AuthenticatorInterface.php | `src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php` | 認証器の5つのメソッド（supports, authenticate, createToken, onAuthenticationSuccess, onAuthenticationFailure）を理解する |
| 1-4 | SecurityRequestAttributes.php | `src/Symfony/Component/Security/Http/SecurityRequestAttributes.php` | リクエスト属性キーの定義 |
| 1-5 | SecurityEvents.php | `src/Symfony/Component/Security/Http/SecurityEvents.php` | INTERACTIVE_LOGIN、SWITCH_USERイベント定義 |

**読解のコツ**: Symfonyのセキュリティシステムはイベント駆動設計であり、KernelEvents::REQUESTイベントをフックポイントとして動作する。FirewallMapInterface::getListeners()の戻り値は3要素の配列（認証リスナー配列、ExceptionListener、LogoutListener）である。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Firewall.php | `src/Symfony/Component/Security/Http/Firewall.php` | セキュリティシステムのメインエントリーポイント |

**主要処理フロー**:
1. **46-50行目**: onKernelRequestでメインリクエストのみを処理対象とする
2. **53行目**: FirewallMapからリクエストに対応するリスナー群を取得
3. **55-57行目**: リスナーの3つの要素（認証リスナー、例外リスナー、ログアウトリスナー）を分解
4. **59-62行目**: ExceptionListenerをイベントディスパッチャーに登録
5. **65-84行目**: ジェネレーターを使い、LogoutListenerを優先度に基づく正しい位置に挿入
6. **107-120行目**: callListenersで各リスナーのsupports/authenticateを順次実行

#### Step 3: ファイアウォールマップを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FirewallMap.php | `src/Symfony/Component/Security/Http/FirewallMap.php` | RequestMatcherに基づくファイアウォール構成の管理 |
| 3-2 | AccessMap.php | `src/Symfony/Component/Security/Http/AccessMap.php` | URLパターンごとのアクセス制御ルール管理 |

**主要処理フロー**:
- **41-50行目** (FirewallMap): getListenersでリクエストに一致する最初のファイアウォール設定を返却
- **36-45行目** (AccessMap): getPatternsでリクエストに一致するアクセス制御ルール（ロール配列、チャネル）を返却

#### Step 4: HTTPユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | HttpUtils.php | `src/Symfony/Component/Security/Http/HttpUtils.php` | セキュリティ関連のHTTPユーティリティ |

**主要処理フロー**:
- **49-59行目**: createRedirectResponseでドメイン検証付きリダイレクト生成
- **66-111行目**: createRequestでサブリクエスト生成（セッション、セキュリティ属性の引き継ぎ）
- **120-143行目**: checkRequestPathでリクエストパスのマッチング（ルート名またはパス）
- **152-184行目**: generateUriでパス/URL/ルート名からURI生成

#### Step 5: 認証リスナーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | CheckCredentialsListener.php | `src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php` | クレデンシャル検証リスナー |
| 5-2 | CsrfProtectionListener.php | `src/Symfony/Component/Security/Http/EventListener/CsrfProtectionListener.php` | CSRF保護リスナー |
| 5-3 | LoginThrottlingListener.php | `src/Symfony/Component/Security/Http/EventListener/LoginThrottlingListener.php` | ログインスロットリングリスナー |
| 5-4 | RememberMeListener.php | `src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php` | Remember Me処理リスナー |

### プログラム呼び出し階層図

```
KernelEvents::REQUEST
    |
    +-- Firewall::onKernelRequest()
           |
           +-- FirewallMap::getListeners()
           |       |
           |       +-- RequestMatcher::matches()
           |
           +-- ExceptionListener::register()
           |
           +-- callListeners() [ジェネレーター]
                  |
                  +-- AuthenticatorListener::supports()
                  +-- AuthenticatorListener::authenticate()
                  |       |
                  |       +-- Authenticator::authenticate()
                  |       +-- Authenticator::createToken()
                  |       +-- CheckCredentialsListener
                  |       +-- CsrfProtectionListener
                  |       +-- RememberMeListener
                  |       +-- Authenticator::onAuthenticationSuccess()
                  |
                  +-- LogoutListener (優先度に基づき配置)
```

### データフロー図

```
[入力]                    [処理]                          [出力]

HTTPリクエスト ---------> Firewall ----------------------> 認証トークン (TokenStorage)
                              |
ファイアウォール設定 ---> FirewallMap::getListeners() ---> セキュリティリスナー群
                              |
認証情報 ----------------> Authenticator::authenticate() -> Passport
(ユーザー名/PW等)             |
                              +-> CheckCredentials -------> 検証結果
                              |
                              +-> onAuthenticationSuccess -> HTTPレスポンス (リダイレクト等)
                              +-> onAuthenticationFailure -> HTTPレスポンス (エラー等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Firewall.php | `src/Symfony/Component/Security/Http/Firewall.php` | ソース | セキュリティシステムのメインエントリーポイント |
| FirewallMap.php | `src/Symfony/Component/Security/Http/FirewallMap.php` | ソース | ファイアウォール設定マップ |
| FirewallMapInterface.php | `src/Symfony/Component/Security/Http/FirewallMapInterface.php` | ソース | ファイアウォールマップインターフェース |
| AccessMap.php | `src/Symfony/Component/Security/Http/AccessMap.php` | ソース | アクセス制御マップ |
| AccessMapInterface.php | `src/Symfony/Component/Security/Http/AccessMapInterface.php` | ソース | アクセス制御マップインターフェース |
| HttpUtils.php | `src/Symfony/Component/Security/Http/HttpUtils.php` | ソース | HTTPユーティリティ |
| SecurityEvents.php | `src/Symfony/Component/Security/Http/SecurityEvents.php` | ソース | セキュリティイベント定数定義 |
| SecurityRequestAttributes.php | `src/Symfony/Component/Security/Http/SecurityRequestAttributes.php` | ソース | リクエスト属性キー定数 |
| AuthenticatorInterface.php | `src/Symfony/Component/Security/Http/Authenticator/AuthenticatorInterface.php` | ソース | 認証器インターフェース |
| FormLoginAuthenticator.php | `src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php` | ソース | フォームログイン認証器 |
| JsonLoginAuthenticator.php | `src/Symfony/Component/Security/Http/Authenticator/JsonLoginAuthenticator.php` | ソース | JSONログイン認証器 |
| HttpBasicAuthenticator.php | `src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php` | ソース | HTTP Basic認証器 |
| AccessTokenAuthenticator.php | `src/Symfony/Component/Security/Http/Authenticator/AccessTokenAuthenticator.php` | ソース | アクセストークン認証器 |
| CheckCredentialsListener.php | `src/Symfony/Component/Security/Http/EventListener/CheckCredentialsListener.php` | ソース | クレデンシャル検証リスナー |
| CsrfProtectionListener.php | `src/Symfony/Component/Security/Http/EventListener/CsrfProtectionListener.php` | ソース | CSRF保護リスナー |
| LoginThrottlingListener.php | `src/Symfony/Component/Security/Http/EventListener/LoginThrottlingListener.php` | ソース | ログインスロットリングリスナー |
| RememberMeListener.php | `src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php` | ソース | Remember Me処理リスナー |
| ParameterBagUtils.php | `src/Symfony/Component/Security/Http/ParameterBagUtils.php` | ソース | パラメータバッグユーティリティ |
