# 00_overview/03_login_session.md # ログイン認証・セッション管理設計書 **保存先**: `/backoffice/docs/00_overview/03_login_session.md` **作成日**: 2026-03-30 **バージョン**: 1.1 **担当**: マスタ管理担当(初代) --- ## 1. 概要・方針 ### 1.1 基本方針 - 認証処理はすべてサーバーサイド(PHP)で行う - クライアント側(JavaScript)でのユーザー情報・権限の保持は **sessionStorage / localStorage を使用しない** - セッション管理は PHPネイティブセッション(`$_SESSION`)を使用する - 権限情報が必要な画面は `get_session.php` に問い合わせて取得する ### 1.2 移行背景 旧来の `login.html` は以下の問題があったため全面移行する。 | 問題 | 内容 | |------|------| | sessionStorage使用 | 作業ルール⑥違反 | | フォールバック権限ハードコード | 特定ユーザーの全権限をJSに直書き | | クライアント側でJSON直接fetch | users.json・employees.jsonがブラウザに丸見え | ### 1.3 権限の移行フェーズ 権限管理は以下の3段階で移行する。 | フェーズ | 状態 | 権限の参照先 | |---------|------|------------| | 仮運用 | employees.jsonの「権限」フィールドに直書き | employees.json | | 暫定運用 | login.php実装後・画面なしで動く | employees.json(変わらず) | | 本運用 | employee_edit.htmlで従事者ごとに権限をチェックボックスで設定・保存時にemployees.jsonを上書き | employees.json(変わらず) | - `login.php` / `get_session.php` は常に `employees.json` の「権限」フィールドを読むだけ。フェーズが変わっても変更不要。 - `permissions.json` は権限IDと表示名の定義マスタ。`employee_edit.html` のチェックボックス生成に使用する。 --- ## 2. ログイン認証フロー ``` [login.html] ユーザーID・パスワード入力 ↓ fetch POST [/master/api/login.php] ① /master/users.json を読み込み、userId + password を照合 ② status !== 'active' → 401 エラー返却 ③ isAdmin フラグを確認(→ 4節参照) ④ /master/employees.json を読み込み、同一SPS_IDのレコードを取得 ⑤ 稼働状況チェック(→ 3節参照) isAdmin: true の場合はスキップ ⑥ session_regenerate_id(true) でセッション固定化防止 ⑦ $_SESSION にユーザー情報・権限・isAdminをセット ⑧ ログイン成功時にセッションIDをactive_sessions.jsonに記録 ⑨ 成功レスポンス(200)を返却 ↓ 成功 [login.html] window.location.href = 'index.html' に遷移 ``` ### 2.1 login.php リクエスト仕様 | 項目 | 内容 | |------|------| | メソッド | POST | | エンドポイント | `/master/api/login.php` | | Content-Type | `application/json` | | ボディ | `{ "userId": "SPS01-00001", "password": "xxx" }` | ### 2.2 login.php レスポンス仕様 **成功時(200)** ```json { "success": true, "name": "真柴 直也", "redirect": "index.html" } ``` **失敗時(401)** ```json { "success": false, "message": "ユーザーIDまたはパスワードが違います" } ``` --- ## 3. ログイン拒否ルール `employees.json` の `稼働状況` フィールドで判定する。 | 稼働状況 | ログイン | 備考 | |---------|---------|------| | 常勤 | 許可 | | | 非常勤 | 許可 | | | 在籍 | 許可 | | | 休職 | 許可 | | | 休業中 | 許可 | | | 退職 | **拒否** | | | 契約終了 | **拒否** | | | 契約解除 | **拒否** | | | 解雇 | **拒否** | | | 緊急ロック | **拒否** | 一時的措置。解除可能(→ 6節参照) | | (employeesに存在しない) | **拒否** | | 拒否時のメッセージ:「このアカウントは無効です」(理由は区別しない) **isAdmin: true のユーザーは稼働状況チェックをスキップする(→ 4節参照)** --- ## 4. 管理者フラグ(isAdmin) ### 4.1 概要 - `users.json` に `isAdmin` フィールドを追加する - `isAdmin: true` のユーザーは `employees.json` の稼働状況チェックをスキップしてログイン可能 - 緊急ロック・退職・解雇状態でも管理者としてシステムに入れる - 初期状態では真柴直也(SPS01-00001)のみ `isAdmin: true` ### 4.2 users.json のデータ構造 ```json { "users": [ { "userId": "SPS01-00001", "password": "sps2024", "name": "真柴 直也", "status": "active", "isAdmin": true }, { "userId": "SPS01-00002", "password": "yoshimi2024", "name": "真柴 良美", "status": "active", "isAdmin": false } ] } ``` ### 4.3 isAdmin の付与・剥奪 - `admin_flag_assign` 権限を保有するユーザーのみ操作可能 - `admin_flag_assign` は通常業務権限(`permissions.json`)とは別枠の特別権限 - 操作画面は `employee_edit.html`(専用セクションとして分離) - 初期状態では真柴直也のみ `admin_flag_assign` を保有 ### 4.4 管理者自身がロックされた場合の救済 - Xserverファイルマネージャで `/master/employees.json` を直接編集し稼働状況を元に戻す - または `/master/users.json` の `isAdmin` を確認・修正する --- ## 5. セッション管理方針 ### 5.1 $_SESSION 保持内容 ```php $_SESSION['sps_user'] = [ 'userId' => 'SPS01-00001', 'name' => '真柴 直也', 'primary_company' => 'SPS', '所属' => ['SPS', 'SCSPS'], 'contractCode' => 'C01', 'isAdmin' => true, 'permissions' => [ 'company_access_sps' => true, 'permission_assign' => true, // ... employees.jsonの「権限」フィールドをそのまま格納 ] ]; ``` ### 5.2 セッション有効期限 - セッションタイムアウト: **120分**(無操作時) - セッション開始: `session_start()` を各APIの冒頭で呼ぶ - セッション再生成: ログイン成功時に `session_regenerate_id(true)` を実行(固定化攻撃対策) ### 5.3 セッションの保存場所 - PHPデフォルトのセッションストレージ(サーバー上の一時ファイル) - Xserverの標準設定に従う ### 5.4 アクティブセッション管理(active_sessions.json) ログイン成功時にセッションIDを記録し、権限変更・緊急ロック時の強制破棄に使用する。 **保存先**: `/backoffice/data/sessions/active_sessions.json` ```json { "sessions": { "SPS01-00003": "abc123xyz..." } } ``` - ログイン成功時:対象ユーザーのセッションIDを記録・上書き - ログアウト時:対象ユーザーのエントリを削除 - セッションタイムアウト時:PHPが自動でセッションファイルを削除するが、active_sessions.jsonのエントリは残る場合がある(ログイン時に上書きされるため実害なし) --- ## 6. 緊急ロック機能 ### 6.1 概要 不祥事・情報漏洩リスク等の緊急時に、対象ユーザーを即時締め出す機能。 ### 6.2 緊急ロックの手順 ``` ① employee_edit.html で対象者の稼働状況を「緊急ロック」に変更 ② 保存 → employees.json の稼働状況を「緊急ロック」に更新 → active_sessions.json から対象者のセッションIDを取得 → サーバー上のセッションファイルを強制削除 ③ 対象者は操作中でも次のリクエスト時に get_session.php が 401 を返す ④ login.html にリダイレクト ⑤ ログインしようとしても稼働状況チェックで拒否される ``` ### 6.3 解雇との違い | 区分 | 性質 | 解除 | |------|------|------| | 緊急ロック | 一時的措置 | 管理者がemployee_edit.htmlで稼働状況を元に戻す | | 解雇 | 恒久的措置 | 原則解除なし | ### 6.4 緊急ロック解除 - `isAdmin: true` の管理者が `employee_edit.html` で稼働状況を「常勤」等に変更・保存 - 対象者は通常通りログイン可能になる ### 6.5 権限変更時のセッション強制破棄 - 緊急ロックに限らず、`employee_edit.html` で権限変更・保存した場合も対象ユーザーのセッションを強制破棄する - 対象者は次のリクエスト時に再ログインを求められ、新しい権限が即時反映される --- ## 7. 各画面の権限取得フロー(get_session.php) ``` [各HTML画面 DOMContentLoaded] ↓ fetch GET [/master/api/get_session.php] ① session_start() ② $_SESSION['sps_user'] の存在確認 ③ 未ログイン → 401 返却 ④ ログイン済み → ユーザー情報・権限・isAdminをJSONで返却 ↓ [各HTML画面] 権限に応じてメニュー表示制御 権限なし → login.html にリダイレクト ``` ### 7.1 get_session.php リクエスト仕様 | 項目 | 内容 | |------|------| | メソッド | GET | | エンドポイント | `/master/api/get_session.php` | ### 7.2 get_session.php レスポンス仕様 **ログイン済み(200)** ```json { "success": true, "userId": "SPS01-00001", "name": "真柴 直也", "primary_company": "SPS", "所属": ["SPS", "SCSPS"], "contractCode": "C01", "isAdmin": true, "permissions": { "company_access_sps": true, "permission_assign": true } } ``` **未ログイン(401)** ```json { "success": false, "message": "未ログイン" } ``` ### 7.3 各画面での実装パターン(共通) ```javascript // 各HTMLのDOMContentLoadedで必ず呼ぶ async function checkSession() { const res = await fetch('/master/api/get_session.php'); if (res.status === 401) { window.location.href = '/login.html'; return null; } return await res.json(); } ``` --- ## 8. ログアウト処理 ### 8.1 ログアウトAPI - エンドポイント: `POST /master/api/logout.php` - 処理: `session_destroy()` を実行してセッションを完全破棄 + `active_sessions.json` から対象エントリを削除 - レスポンス: `{ "success": true }` → クライアントが `login.html` にリダイレクト ### 8.2 実装場所 - 各画面ヘッダーのユーザードロップダウン「ログアウト」ボタンから呼び出す - `logout.php` は今後 `master/api/` 配下に作成する(全体管理者担当) --- ## 9. エラーレスポンス定義 | HTTPステータス | 原因 | メッセージ | |--------------|------|-----------| | 400 | リクエストパラメータ不足 | 必須パラメータが不足しています | | 401 | 認証失敗(ID/PW不一致) | ユーザーIDまたはパスワードが違います | | 401 | 退職・緊急ロック・無効アカウント | このアカウントは無効です | | 401 | 未ログイン(get_session) | 未ログイン | | 500 | JSONファイル読み込み失敗 | システムエラーが発生しました | --- ## 10. 今後の拡張 - ログイン履歴ログ(`/data/logs/login_log.json`)の実装は将来検討 - パスワード平文保存は意図的設計(不正時の即時ロックアウトのため)。変更禁止 --- ## 11. 改訂履歴 | 日付 | 版 | 担当 | 内容 | 理由・影響範囲 | |------|----|------|------|--------------| | 2026-03-30 | 1.0 | マスタ管理担当(初代) | 初版作成 | login.htmlのsessionStorage除去・PHPセッション移行に伴う設計書新規作成 | | 2026-04-04 | 1.1 | マスタ管理担当(2代目) | 1.3節追加(権限移行フェーズ)、2節フロー改訂、3節に緊急ロック追加、4節新設(isAdmin)、5.4節新設(active_sessions.json)、6節新設(緊急ロック機能)、7節旧5節を改訂(isAdmin追加)、8節旧6節を改訂、9節旧7節を改訂、10節旧8節を改訂 | 打ち合わせ確定事項の反映:緊急ロック・isAdmin・セッション強制破棄・権限移行フェーズ |