# 機能設計書 20-Security Core

## 概要

本ドキュメントは、Symfony Security Coreコンポーネントの機能設計を記述する。Security Coreは、認証・認可の中核ライブラリを提供し、ユーザープロバイダー、アクセス決定マネージャー、ロール階層等の機能を統合する。

### 本機能の処理概要

**業務上の目的・背景**：Webアプリケーションにおいて、「誰がアクセスしているか」（認証）と「何にアクセスできるか」（認可）の管理は最重要な関心事である。Security Coreは、認証トークン、認可Voter、ユーザーインターフェース等の抽象化を提供し、柔軟で拡張可能なセキュリティアーキテクチャを実現する。

**機能の利用シーン**：ユーザーログイン後のアクセス制御、APIエンドポイントの認可チェック、管理画面へのロールベースアクセス制御、カスタムVoterによるドメイン固有の認可ロジック実装に利用される。

**主要な処理内容**：
1. 認証トークンの管理（TokenInterface、TokenStorage）
2. 認可チェック（AuthorizationChecker::isGranted）
3. アクセス決定（AccessDecisionManager、Voterチェーン）
4. 決定戦略（AffirmativeStrategy等）
5. ユーザーインターフェースとプロバイダー（UserInterface、UserProviderInterface）
6. ロールと権限の管理
7. 認証信頼性の判定（AuthenticationTrustResolver）
8. 式言語によるアクセス制御（ExpressionLanguage統合）
9. パスワードハッシュ検証とリハッシュ

**関連システム・外部連携**：SecurityBundle（DI統合・設定）、Security HTTP（ファイアウォール・認証リスナー）、Security CSRF（CSRFトークン管理）、PasswordHasher（パスワードハッシュ化）、ExpressionLanguage（アクセス制御式）と連携する。

**権限による制御**：本コンポーネント自体がセキュリティの中核であり、認証トークンとVoterベースの認可メカニズムを提供する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | セキュリティパネル | 主機能 | 認証ユーザー情報、ロール、アクセス決定の結果の表示 |

## 機能種別

認証 / 認可 / アクセス制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| attribute | mixed | Yes | チェック対象の権限属性（ROLE_ADMIN、IS_AUTHENTICATED等） | - |
| subject | mixed | No | チェック対象のサブジェクト（エンティティ等） | - |
| token | TokenInterface | Yes | 認証トークン（ユーザー情報保持） | TokenInterface実装 |
| user | UserInterface | Yes | ユーザーオブジェクト | UserInterface実装 |
| attributes | array | Yes | Voter投票の対象属性配列 | - |

### 入力データソース

認証プロセスで生成されたトークン（TokenStorage）、アプリケーションコードからのisGranted呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isGranted | bool | アクセスが許可されたかどうか |
| accessDecision | AccessDecision | 決定の詳細情報（Voter投票結果含む） |
| vote | int | 個別Voterの投票結果（ACCESS_GRANTED=1、ACCESS_ABSTAIN=0、ACCESS_DENIED=-1） |

### 出力先

呼び出し元への返却値。AccessDecisionオブジェクトにはVoter別の投票結果が蓄積される。

## 処理フロー

### 処理シーケンス

```
1. isGranted呼び出し（AuthorizationChecker）
   └─ TokenStorageから現在のトークンを取得（未認証時はNullToken）
2. AccessDecisionManager::decide呼び出し
   └─ 登録されたVoterへの投票依頼
3. Voter投票（collectResults）
   └─ 各VoterがACCESS_GRANTED/DENIED/ABSTAINを返却
4. 決定戦略による判定
   └─ AffirmativeStrategy（1つでもGRANTEDなら許可）等
5. AccessDecisionへの結果蓄積
   └─ 各Voterの投票結果とメッセージを蓄積
6. 結果返却
```

### フローチャート

```mermaid
flowchart TD
    A[isGranted呼び出し] --> B[トークン取得]
    B --> C{トークンあり?}
    C -->|No| D[NullToken生成]
    C -->|Yes| E[既存トークン使用]
    D --> F[AccessDecisionManager::decide]
    E --> F
    F --> G[Voter投票ループ]
    G --> H[Voter::vote]
    H --> I{結果}
    I -->|GRANTED| J[Vote記録]
    I -->|DENIED| J
    I -->|ABSTAIN| J
    J --> K{全Voter完了?}
    K -->|No| H
    K -->|Yes| L[決定戦略判定]
    L --> M{許可?}
    M -->|Yes| N[true返却]
    M -->|No| O[false返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-20-01 | AffirmativeStrategy | デフォルトの決定戦略。1つでもGRANTEDを返すVoterがあれば許可 | AccessDecisionManager |
| BR-20-02 | CacheableVoter | CacheableVoterInterfaceを実装するVoterは属性とオブジェクト型でキャッシュされる | getVoters |
| BR-20-03 | 単一属性制限 | decide()はデフォルトで複数属性を受け付けない（allowMultipleAttributes=falseがデフォルト） | decide |
| BR-20-04 | NullToken | 未認証時はNullTokenが使用される | isGranted（トークンなし時） |
| BR-20-05 | isGrantedForUser | 任意のユーザーに対してオフラインで認可チェックが可能 | AuthorizationChecker::isGrantedForUser |
| BR-20-06 | Vote結果 | ACCESS_GRANTED=1、ACCESS_ABSTAIN=0、ACCESS_DENIED=-1の3値 | VoterInterface |

### 計算ロジック

Voter投票結果の集約: 各VoterのACCESS_GRANTED/DENIED/ABSTAINを収集し、決定戦略（Affirmative、Consensus、Unanimous、Priority等）に基づいて最終判定を行う。CacheableVoterの場合、supportsAttribute/supportsTypeの結果をキャッシュして再利用する。

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

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

本コンポーネント自体はデータベース操作を行わない。UserProviderInterfaceの実装がデータベースからユーザー情報を取得する場合がある。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidArgumentException | decide()に複数属性を渡した場合（allowMultipleAttributes=false時） | 属性を1つずつ渡すか、allowMultipleAttributes=trueに設定 |
| - | LogicException | Voterが不正な値を返した場合 | Voterの実装を修正（ACCESS_GRANTED/DENIED/ABSTAINのいずれかを返す） |
| - | AccessDeniedException | アクセス拒否時 | 権限設定の確認、Voter実装の確認 |

### リトライ仕様

リトライは行わない。

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

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

## パフォーマンス要件

- CacheableVoterInterfaceによるVoter結果のキャッシュで重複チェックを回避
- supportsAttribute/supportsTypeのキャッシュにより、無関係なVoterの呼び出しをスキップ
- accessDecisionStackによるネストしたアクセスチェックの管理

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

- 認証トークンのシリアライズ時に機密情報（パスワード等）が含まれないよう__serialize/__unserializeで制御
- NullTokenの使用により、未認証状態でも一貫したアクセス制御フローを維持
- OfflineTokenInterfaceにより、オフライン認可チェック用のトークンを区別

## 備考

- TraceableAccessDecisionManagerにより、Voter投票の詳細をWebProfilerで確認可能
- ExpressionLanguage統合（Authorization/ExpressionLanguage.php）により、is_granted等のセキュリティ関数を式で使用可能
- Signature名前空間にはHMACベースの署名検証機能が含まれる
- Test名前空間にはテスト用のユーティリティが含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | UserInterface.php | `src/Symfony/Component/Security/Core/User/UserInterface.php` | ユーザーの基本契約。getRoles()、getUserIdentifier()の2メソッド |
| 1-2 | TokenInterface.php | `src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php` | 認証トークンの契約。ユーザー情報、ロール名、属性の管理 |
| 1-3 | VoterInterface.php | `src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php` | Voterの契約。ACCESS_GRANTED=1、ACCESS_ABSTAIN=0、ACCESS_DENIED=-1の3定数とvote()メソッド |

**読解のコツ**: Security Coreは「Token（誰か）→ AuthorizationChecker（チェック要求）→ AccessDecisionManager（判定）→ Voter（投票）」のチェーンで動作する。UserInterfaceはgetRoles()とgetUserIdentifier()の2メソッドのみの軽量インターフェース。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AuthorizationChecker.php | `src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php` | セキュリティの主エントリーポイント。isGranted()とisGrantedForUser() |

**主要処理フロー**:
1. **37-41行目**: コンストラクタ。TokenStorageとAccessDecisionManagerの注入
2. **43-58行目**: isGranted()。トークン取得（未認証時はNullToken）、accessDecisionStack管理、decide()呼び出し
3. **60-71行目**: isGrantedForUser()。任意ユーザーのOfflineToken生成、tokenStack経由のネストチェック

#### Step 3: アクセス決定メカニズム

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AccessDecisionManager.php | `src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php` | Voter投票の収集と決定戦略の適用 |
| 3-2 | AccessDecision.php | `src/Symfony/Component/Security/Core/Authorization/AccessDecision.php` | 決定結果の詳細情報（Voter投票リスト含む） |

**主要処理フロー**:
- **45-50行目（AccessDecisionManager）**: コンストラクタ。Voterリストとデフォルト戦略（AffirmativeStrategy）
- **55-80行目（AccessDecisionManager）**: decide()。accessDecisionStack管理、collectResults→strategy.decideのチェーン
- **85-102行目（AccessDecisionManager）**: collectResults()。各Voterへのvote()呼び出し、結果検証、Vote記録
- **107-149行目（AccessDecisionManager）**: getVoters()。CacheableVoterのsupportsAttribute/supportsTypeキャッシュ

#### Step 4: Voter実装

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | VoterInterface.php | `src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php` | Voterインターフェース（ACCESS_GRANTED/ABSTAIN/DENIED定数） |
| 4-2 | CacheableVoterInterface.php | `src/Symfony/Component/Security/Core/Authorization/Voter/CacheableVoterInterface.php` | キャッシュ可能Voterの拡張インターフェース |
| 4-3 | Vote.php | `src/Symfony/Component/Security/Core/Authorization/Voter/Vote.php` | 個別投票結果の詳細情報 |

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

```
AuthorizationChecker::isGranted()
    │
    ├─ TokenStorage::getToken()
    │      └─ NullToken（未認証時）
    │
    └─ AccessDecisionManager::decide()
           │
           ├─ collectResults()
           │      └─ VoterInterface::vote()（各Voterを順次呼び出し）
           │             ├─ CacheableVoter: supportsAttribute/supportsType チェック
           │             └─ Vote オブジェクト生成・記録
           │
           └─ AccessDecisionStrategyInterface::decide()
                  ├─ AffirmativeStrategy（1つでもGRANTED→許可）
                  ├─ ConsensusStrategy（多数決）
                  ├─ UnanimousStrategy（全員GRANTED→許可）
                  └─ PriorityStrategy（最初の非ABSTAIN結果）

AuthorizationChecker::isGrantedForUser()
    │
    ├─ OfflineToken生成（AbstractToken匿名クラス）
    └─ isGranted()（上記と同じフロー）
```

### データフロー図

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

attribute            ───▶ AuthorizationChecker         ───▶ bool (isGranted)
(ROLE_ADMIN等)             │
subject              ───▶ │
(Entity等)                 ├─ TokenStorage（トークン取得）
                           │
                           └─ AccessDecisionManager
                                  │
                                  ├─ Voter1::vote() ───▶ GRANTED/DENIED/ABSTAIN
                                  ├─ Voter2::vote() ───▶ GRANTED/DENIED/ABSTAIN
                                  └─ Strategy判定   ───▶ AccessDecision
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AuthorizationChecker.php | `src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php` | ソース | 認可チェックのメインエントリーポイント |
| AccessDecisionManager.php | `src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php` | ソース | Voter投票と決定戦略の管理 |
| AccessDecision.php | `src/Symfony/Component/Security/Core/Authorization/AccessDecision.php` | ソース | 決定結果の詳細情報 |
| VoterInterface.php | `src/Symfony/Component/Security/Core/Authorization/Voter/VoterInterface.php` | ソース | Voterインターフェース |
| CacheableVoterInterface.php | `src/Symfony/Component/Security/Core/Authorization/Voter/CacheableVoterInterface.php` | ソース | キャッシュ可能Voter |
| Vote.php | `src/Symfony/Component/Security/Core/Authorization/Voter/Vote.php` | ソース | 投票結果 |
| TraceableVoter.php | `src/Symfony/Component/Security/Core/Authorization/Voter/TraceableVoter.php` | ソース | トレース可能Voterラッパー |
| TokenInterface.php | `src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php` | ソース | 認証トークンインターフェース |
| UserInterface.php | `src/Symfony/Component/Security/Core/User/UserInterface.php` | ソース | ユーザーインターフェース |
| AuthenticationTrustResolver.php | `src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php` | ソース | 認証信頼性判定 |
| Strategy/ | `src/Symfony/Component/Security/Core/Authorization/Strategy/` | ソース | 決定戦略群 |
| ExpressionLanguage.php | `src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php` | ソース | セキュリティ式言語 |
| Signature/ | `src/Symfony/Component/Security/Core/Signature/` | ソース | HMAC署名 |
| Validator/ | `src/Symfony/Component/Security/Core/Validator/` | ソース | バリデータ統合 |
