# 機能設計書 24-セッション管理

## 概要

本ドキュメントは、Laravel Frameworkのセッション管理機能（SessionManager）の設計仕様を記載する。SessionManagerは複数のセッションドライバを管理し、ユーザーセッションの永続化と取得を提供する。

### 本機能の処理概要

SessionManagerは、PHPのネイティブセッション機構を使用せず、独自のセッション管理機構を提供するコンポーネントである。複数のストレージバックエンドをサポートし、セッションデータの暗号化やシリアライゼーション方式の選択が可能。

**業務上の目的・背景**：Webアプリケーションにおいて、HTTPはステートレスなプロトコルであるため、ユーザーの状態を維持するにはセッション機構が必要となる。SessionManagerは、ログイン状態の維持、ショッピングカート情報の保持、フラッシュメッセージの伝達、CSRF保護トークンの管理など、ステートフルなWeb体験を実現するための基盤を提供する。

**機能の利用シーン**：ユーザー認証状態の管理、フォーム入力値の一時保存（リダイレクト後の復元）、フラッシュメッセージ（操作完了通知等）、CSRFトークン管理、ショッピングカートなどの一時データ保存。

**主要な処理内容**：
1. ドライバに応じたセッションハンドラの生成（File、Database、Redis等）
2. セッションストア（Store/EncryptedStore）の構築
3. セッションIDの生成と検証
4. セッションデータの読み込みと保存
5. フラッシュデータの管理（次リクエストで自動削除）
6. CSRFトークンの生成と検証

**関連システム・外部連携**：キャッシュドライバ（Redis、Memcached等）、データベース、Cookieマネージャー、暗号化サービス（Encrypter）との連携。

**権限による制御**：セッション機能自体には権限制御はない。セッションに格納された認証情報を元に認可処理が行われる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | 419 Page Expired | 主機能 | CSRFトークン期限切れエラー表示 |

## 機能種別

セッション管理 / 状態管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| driver | string | No | セッションドライバ名 | 有効なドライバ名 |
| lifetime | int | Yes | セッション有効期間（分） | 正の整数 |
| path | string | Yes | Cookie のパス | 有効なパス |
| domain | string | No | Cookie のドメイン | 有効なドメイン |
| secure | bool | No | HTTPS のみ | true/false |
| http_only | bool | No | JavaScript からのアクセス禁止 | true/false |
| same_site | string | No | SameSite 属性 | lax/strict/none |

### 入力データソース

- 設定ファイル（config/session.php）
- リクエストCookieからのセッションID

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| session | Store | セッションストアインスタンス |
| cookie | Cookie | セッションID を含む Cookie |

### 出力先

- セッションストレージ（File/Database/Redis/Memcached等）
- レスポンスCookie（セッションID）

## 処理フロー

### 処理シーケンス

```
1. SessionManager::driver()でドライバを取得
   └─ getDefaultDriver()でデフォルトドライバ名を取得
   └─ create{Driver}Driver()でハンドラを生成

2. buildSession()でセッションストアを構築
   └─ encrypt設定でStore/EncryptedStoreを選択
   └─ シリアライゼーション方式を設定（php/json）

3. Store::start()でセッションを開始
   └─ loadSession()でハンドラからデータ読み込み
   └─ CSRFトークンがなければ生成

4. Store::save()でセッションを保存
   └─ ageFlashData()でフラッシュデータを処理
   └─ ハンドラにデータを書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[SessionManager::driver]
    B --> C{ドライバ種別}
    C -->|file| D[FileSessionHandler]
    C -->|database| E[DatabaseSessionHandler]
    C -->|redis| F[CacheBasedSessionHandler<br>Redis]
    C -->|cookie| G[CookieSessionHandler]
    C -->|array| H[ArraySessionHandler]
    D --> I[buildSession]
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J{暗号化有効?}
    J -->|Yes| K[EncryptedStore]
    J -->|No| L[Store]
    K --> M[セッション開始]
    L --> M
    M --> N[データ読み込み]
    N --> O{CSRFトークン存在?}
    O -->|No| P[トークン生成]
    O -->|Yes| Q[セッション利用可能]
    P --> Q
    Q --> R[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | セッションID長 | セッションIDは40文字の英数字 | 常時 |
| BR-02 | CSRFトークン | 新規セッションではCSRFトークンを自動生成 | セッション開始時 |
| BR-03 | フラッシュデータ | フラッシュデータは次リクエストで自動削除 | セッション保存時 |
| BR-04 | ガベージコレクション | lottery設定に基づき確率的にGCを実行 | セッション開始時 |
| BR-05 | セッション再生成 | 認証成功時にセッションIDを再生成すべき | セキュリティ要件 |

### 計算ロジック

- セッションID: Str::random(40)で生成
- セッション有効期限: 現在時刻 + lifetime分
- GC確率: lottery[0] / lottery[1]（例: 2/100 = 2%）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| セッション読み込み | sessions | SELECT | セッションIDでデータ取得 |
| セッション保存 | sessions | INSERT/UPDATE | セッションデータを保存 |
| ガベージコレクション | sessions | DELETE | 期限切れセッションを削除 |

### テーブル別操作詳細

#### sessions テーブル（Databaseドライバ使用時）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, payload, last_activity | WHERE id = ? | 読み込み |
| INSERT/UPDATE | payload, last_activity | セッションデータ | 保存 |
| DELETE | - | WHERE last_activity < ? | GC |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TokenMismatchException | CSRFエラー | CSRFトークン不一致 | 419エラー画面を表示 |
| DecryptException | 復号化エラー | 暗号化セッションの復号失敗 | セッションをリセット |
| RuntimeException | 設定エラー | 無効なドライバ名 | 設定ファイルを確認 |

### リトライ仕様

セッション読み込み/保存の失敗時のリトライは各ドライバの責務。Redisドライバ等では接続リトライが設定可能。

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

Databaseドライバ使用時、セッション保存はトランザクション内で実行されない（独立した操作）。アプリケーショントランザクションとは分離される。

## パフォーマンス要件

- セッションデータサイズ: 推奨1MB以下
- Redisドライバ: 低レイテンシでの読み書きを実現
- Fileドライバ: ファイルシステムIOに依存
- ブロッキングセッション: 同一セッションへの同時アクセスをロックで制御可能

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

- **セッションID**: 暗号学的に安全な乱数で生成
- **セッション固定攻撃対策**: 認証成功時にregenerateを推奨
- **暗号化オプション**: EncryptedStoreでセッションデータを暗号化
- **CSRFトークン**: セッションに紐付けて管理
- **Cookie属性**: HttpOnly、Secure、SameSiteを適切に設定
- **セッションハイジャック対策**: HTTPS必須化を推奨

## 備考

- SessionServiceProviderで自動登録
- 'session'エイリアスでコンテナから解決可能
- StartSessionミドルウェアで自動的にセッションを開始・保存

---

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

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

### 推奨読解順序

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

まず、セッションの契約インターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Session.php | `src/Illuminate/Contracts/Session/Session.php` | セッションの契約インターフェース |

**読解のコツ**: get/put/has/forget/flash等の基本操作を確認。

#### Step 2: マネージャクラスを理解する

セッションドライバの管理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SessionManager.php | `src/Illuminate/Session/SessionManager.php` | ドライバ管理とファクトリ |
| 2-2 | SessionServiceProvider.php | `src/Illuminate/Session/SessionServiceProvider.php` | サービス登録 |

**主要処理フロー**:
- **28-31行目**: createNullDriver()でNullハンドラを生成
- **63-81行目**: createFileDriver()/createNativeDriver()でFileハンドラを生成
- **88-97行目**: createDatabaseDriver()でDBハンドラを生成
- **136-145行目**: createRedisDriver()でRedisハンドラを生成
- **190-200行目**: buildSession()でStore/EncryptedStoreを選択

#### Step 3: セッションストアを理解する

実際のセッション操作を行うStoreクラスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Store.php | `src/Illuminate/Session/Store.php` | メインのセッションストア |
| 3-2 | EncryptedStore.php | `src/Illuminate/Session/EncryptedStore.php` | 暗号化対応ストア |

**主要処理フロー**:
- **85-91行目**: コンストラクタで名前、ハンドラ、シリアライゼーションを設定
- **98-107行目**: start()でセッションを開始、CSRFトークン生成
- **181-192行目**: save()でセッションを保存、フラッシュデータを処理
- **233-240行目**: ageFlashData()でフラッシュデータを経過処理
- **470-480行目**: flash()でフラッシュデータを設定
- **618-623行目**: regenerate()でセッションIDを再生成
- **743-758行目**: token()/regenerateToken()でCSRFトークン管理

#### Step 4: セッションハンドラを理解する

各ストレージバックエンドの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FileSessionHandler.php | `src/Illuminate/Session/FileSessionHandler.php` | ファイルベースハンドラ |
| 4-2 | DatabaseSessionHandler.php | `src/Illuminate/Session/DatabaseSessionHandler.php` | DBベースハンドラ |
| 4-3 | CacheBasedSessionHandler.php | `src/Illuminate/Session/CacheBasedSessionHandler.php` | キャッシュベースハンドラ |

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

```
SessionServiceProvider::register()
    │
    └─ SessionManager (singleton)

SessionManager::driver()
    │
    ├─ getDefaultDriver()
    │      └─ config('session.driver')
    │
    └─ create{Driver}Driver()
           │
           ├─ FileSessionHandler / DatabaseSessionHandler / etc.
           │
           └─ buildSession()
                  │
                  ├─ config('session.encrypt')
                  │      └─ true: EncryptedStore
                  │      └─ false: Store
                  │
                  └─ Store::__construct()

Store::start()
    │
    ├─ loadSession()
    │      └─ readFromHandler()
    │             └─ SessionHandler::read()
    │
    └─ regenerateToken() (if needed)

Store::save()
    │
    ├─ ageFlashData()
    │
    └─ SessionHandler::write()
```

### データフロー図

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

Cookie
session_id ───────▶ SessionManager::driver()
    │                      │
    │                      ▼
    │              SessionHandler
    │                      │
    │                      ▼
    │              Store::start()
    │                      │
    │              ┌───────┴───────┐
    │              ▼               ▼
    │         [読み込み]      [新規作成]
    │              │               │
    │              ▼               ▼
    │         ストレージ      regenerateToken()
    │         からデータ取得
    │              │
    │              ▼
    └──────▶ セッション利用
                   │
                   ▼
              Store::save()
                   │
                   ▼
              ストレージに保存 ───▶ Cookie
                                 session_id
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SessionManager.php | `src/Illuminate/Session/SessionManager.php` | ソース | ドライバ管理 |
| Store.php | `src/Illuminate/Session/Store.php` | ソース | セッションストア |
| EncryptedStore.php | `src/Illuminate/Session/EncryptedStore.php` | ソース | 暗号化ストア |
| FileSessionHandler.php | `src/Illuminate/Session/FileSessionHandler.php` | ソース | Fileハンドラ |
| DatabaseSessionHandler.php | `src/Illuminate/Session/DatabaseSessionHandler.php` | ソース | DBハンドラ |
| CacheBasedSessionHandler.php | `src/Illuminate/Session/CacheBasedSessionHandler.php` | ソース | Cacheハンドラ |
| CookieSessionHandler.php | `src/Illuminate/Session/CookieSessionHandler.php` | ソース | Cookieハンドラ |
| SessionServiceProvider.php | `src/Illuminate/Session/SessionServiceProvider.php` | ソース | サービス登録 |
| Session.php | `src/Illuminate/Contracts/Session/Session.php` | インターフェース | 契約定義 |
| TokenMismatchException.php | `src/Illuminate/Session/TokenMismatchException.php` | ソース | CSRF例外 |
