# 機能設計書 23-SecurityBundle

## 概要

本ドキュメントは、Symfony SecurityBundleの機能設計を記述する。SecurityBundleはSecurityコンポーネント群とSymfonyフルスタックフレームワークの統合を提供し、セキュリティ設定のDI統合、ファイアウォール設定等を実現する。

### 本機能の処理概要

**業務上の目的・背景**：Symfonyのセキュリティシステムは複数のコンポーネント（Security Core、Security HTTP、Security CSRF）から構成される複雑なシステムである。SecurityBundleはこれらを統合し、YAMLやPHP設定ファイルによる宣言的なセキュリティ設定を可能にする。これにより、開発者はセキュリティの内部実装を意識することなく、設定ファイルだけでファイアウォール、認証、認可を構築できる。

**機能の利用シーン**：Symfonyアプリケーションのセキュリティ設定全般。ファイアウォール定義、認証方式（フォームログイン、HTTP Basic等）の設定、アクセス制御ルール定義、ユーザープロバイダー設定、Remember Me設定、CSRF保護設定、プログラムからのログイン・ログアウト操作等。

**主要な処理内容**：
1. Securityクラスによるセキュリティ操作のファサード（getUser, isGranted, login, logout等）
2. DependencyInjectionによるセキュリティサービスの自動登録とコンパイラパス
3. ファイアウォール設定に基づく認証器（Authenticator）の自動構成
4. アクセス制御設定（access_control）に基づくAccessMapの構築
5. DataCollectorによるWebプロファイラーへのセキュリティ情報提供
6. セキュリティ関連コマンド（debug:security等）の提供

**関連システム・外部連携**：Security Core（認証・認可エンジン）、Security HTTP（HTTP統合）、Security CSRF（CSRF保護）、DependencyInjection（サービスコンテナ）、HttpKernel（Profiler）、FrameworkBundle（フレームワーク統合基盤）と連携する。

**権限による制御**：Security::isGranted()メソッドにより、ロール（ROLE_USER、ROLE_ADMIN等）やカスタムVoterに基づくアクセス制御を提供。isGrantedForUser()によりCLIコンテキストでの権限チェックも可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | セキュリティパネル | 主機能 | 認証・認可のセキュリティ情報を表示するパネル（SecurityBundle提供テンプレート） |

## 機能種別

フレームワーク統合 / セキュリティ設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| security設定 | array | Yes | security.yamlのセキュリティ設定ツリー | SecurityExtensionで検証 |
| UserInterface | UserInterface | Yes（login時） | ログイン対象のユーザー | UserInterface実装 |
| attributes | mixed | Yes（isGranted時） | チェック対象の権限属性 | Voterが判定 |

### 入力データソース

security.yaml設定ファイル、DIコンテナ、リクエストスタック、トークンストレージ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| UserInterface | UserInterface/null | 現在の認証ユーザー |
| isGranted | bool | 権限チェック結果 |
| AccessDecision | AccessDecision | アクセス判定の詳細情報 |
| FirewallConfig | FirewallConfig/null | 現在のファイアウォール設定 |
| Response | Response/null | login/logoutの結果レスポンス |

### 出力先

HTTPレスポンス、トークンストレージ、セッション、WebプロファイラーDataCollector

## 処理フロー

### 処理シーケンス

```
1. バンドル初期化
   └─ SecurityBundle::build()でコンパイラパス登録
2. セキュリティ設定読み込み
   └─ SecurityExtension::load()で設定ツリー解析
3. ファイアウォール構築
   └─ 各ファイアウォールの認証器・リスナーをDIコンテナに登録
4. アプリケーション実行時
   └─ Security::getUser() / isGranted() / login() / logout()
5. プログラム的ログイン
   └─ Security::login() -> AuthenticatorManager::authenticateUser()
6. プログラム的ログアウト
   └─ Security::logout() -> LogoutEventディスパッチ
```

### フローチャート

```mermaid
flowchart TD
    A[Security::login] --> B[リクエスト取得]
    B --> C[ファイアウォール名特定]
    C --> D[認証器取得]
    D --> E[UserChecker::checkPreAuth]
    E --> F[AuthenticatorManager::authenticateUser]
    F --> G[認証トークン生成・保存]
    G --> H[Response返却]

    I[Security::logout] --> J[トークン存在確認]
    J --> K{CSRF検証?}
    K -->|Yes| L[CSRFトークン検証]
    K -->|No| M[LogoutEventディスパッチ]
    L --> M
    M --> N[トークン削除]
    N --> O[Response返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | ファイアウォール必須 | login/logoutにはリクエストがファイアウォール配下にある必要がある | Security::login/logout呼び出し時 |
| BR-23-02 | 認証器一意性 | 複数認証器がある場合、login時に明示的にauthenticatorNameを指定する必要がある | Security::login()で複数認証器設定時 |
| BR-23-03 | ログアウトCSRF検証 | デフォルトでCSRFトークン検証を行い、無効な場合LogoutExceptionを投げる | Security::logout()呼び出し時 |

### 計算ロジック

特になし。

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

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

直接的なデータベース操作は行わない。ユーザープロバイダー経由でのユーザー読み込みはアプリケーション層に委任される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LogicException | リクエストコンテキストなしでlogin/logout | HTTPリクエストコンテキスト内で使用 |
| - | LogicException | ファイアウォール配下にないリクエストでlogin/logout | 適切なファイアウォール設定を追加 |
| - | LogicException | 複数認証器で認証器名未指定 | authenticatorNameパラメータを指定 |
| - | LogoutException | CSRFトークンが無効 | 正しいCSRFトークンを送信 |
| - | RuntimeException | 指定されたファイアウォールに認証器が未設定 | ファイアウォール設定に認証器を追加 |

### リトライ仕様

リトライは不要。

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

直接的なトランザクション管理は行わない。

## パフォーマンス要件

Securityクラスはサービスコンテナから遅延読み込みされるため、セキュリティ操作が不要なリクエストではオーバーヘッドは最小限。

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

- Security::logout()のCSRFトークン検証によるCSRF攻撃でのログアウト強制の防止
- isGrantedForUser()によるCLIコンテキストでの安全な権限チェック
- AccessDecisionクラスによるアクセス判定の監査可能性

## 備考

SecurityBundleはSymfonyセキュリティシステムのエントリーポイントであり、アプリケーション開発者が最も頻繁に利用するセキュリティAPIを提供する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Security.php | `src/Symfony/Bundle/SecurityBundle/Security.php` | Securityファサードクラスの全体構造。AuthorizationCheckerInterfaceとUserAuthorizationCheckerInterfaceを実装 |

**読解のコツ**: SecurityクラスはContainerInterfaceを通じて各セキュリティサービスに遅延アクセスする。DIコンテナのサービスロケータパターンが使われている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Security.php | `src/Symfony/Bundle/SecurityBundle/Security.php` | 主要メソッドの動作を理解 |

**主要処理フロー**:
1. **50-57行目**: getUser()でトークンストレージからユーザーを取得
2. **62-66行目**: isGranted()でauthorization_checkerに委任
3. **81-85行目**: isGrantedForUser()でuser_authorization_checkerに委任
4. **114-133行目**: login()でファイアウォール特定 -> 認証器取得 -> UserChecker -> authenticateUser
5. **144-178行目**: logout()でCSRF検証 -> LogoutEventディスパッチ -> トークン削除
6. **180-211行目**: getAuthenticator()でファイアウォール内の認証器を名前またはIDで検索

#### Step 3: DI拡張を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SecurityBundle.php | `src/Symfony/Bundle/SecurityBundle/SecurityBundle.php` | バンドルのブートストラップ処理 |
| 3-2 | DependencyInjection/ | `src/Symfony/Bundle/SecurityBundle/DependencyInjection/` | セキュリティ設定の読み込みとサービス登録 |

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

```
Security (ファサード)
    |
    +-- getUser()
    |       +-- TokenStorage::getToken()
    |       +-- Token::getUser()
    |
    +-- isGranted()
    |       +-- AuthorizationChecker::isGranted()
    |
    +-- login()
    |       +-- RequestStack::getCurrentRequest()
    |       +-- getFirewallConfig()
    |       +-- getAuthenticator()
    |       +-- UserChecker::checkPreAuth()
    |       +-- AuthenticatorManager::authenticateUser()
    |
    +-- logout()
            +-- TokenStorage::getToken()
            +-- FirewallMap::getFirewallConfig()
            +-- CsrfTokenManager::isTokenValid()
            +-- EventDispatcher::dispatch(LogoutEvent)
            +-- TokenStorage::setToken(null)
```

### データフロー図

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

security.yaml設定 -------> SecurityExtension::load() -----> DIコンテナ（サービス定義）
                                |
UserInterface ------------> Security::login() ------------> Response / Token
                                |
                           AuthenticatorManager
                                |
Request -----------------> Security::logout() ------------> Response
                                |
                           LogoutEvent dispatch

mixed attributes --------> Security::isGranted() ---------> bool
                                |
                           AccessDecisionManager
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Security.php | `src/Symfony/Bundle/SecurityBundle/Security.php` | ソース | セキュリティ操作ファサード |
| SecurityBundle.php | `src/Symfony/Bundle/SecurityBundle/SecurityBundle.php` | ソース | バンドル定義 |
| DependencyInjection/ | `src/Symfony/Bundle/SecurityBundle/DependencyInjection/` | ソース | DI拡張・設定処理 |
| DataCollector/ | `src/Symfony/Bundle/SecurityBundle/DataCollector/` | ソース | プロファイラーデータコレクター |
| Command/ | `src/Symfony/Bundle/SecurityBundle/Command/` | ソース | セキュリティ関連CLIコマンド |
| Resources/ | `src/Symfony/Bundle/SecurityBundle/Resources/` | 設定 | サービス定義、テンプレート |
| Security/FirewallConfig.php | `src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php` | ソース | ファイアウォール設定データクラス |
