# 機能設計書 12-オンラインユーザー

## 概要

本ドキュメントは、RuoYiシステムにおけるオンラインユーザー監視機能の詳細設計を記述する。オンラインユーザー機能は、現在システムにログインしているユーザーをリアルタイムで監視し、必要に応じて強制ログアウトを実行できる機能を提供する。

### 本機能の処理概要

オンラインユーザー機能は、現在有効なセッションを持つユーザーの一覧を表示し、管理者が不正なセッションや不要なセッションを強制的に終了させることができる機能を提供する。

**業務上の目的・背景**：エンタープライズシステムにおいて、同時ログインユーザーの監視は運用管理上不可欠である。セキュリティインシデント発生時の迅速なセッション無効化、システムリソース管理、ユーザーの業務状況把握などに活用される。特に、不正アクセス検知時に該当セッションを即座に強制ログアウトさせることで、被害を最小限に抑えることができる。

**機能の利用シーン**：
- システム管理者が現在のログインユーザー数を確認する際
- セキュリティインシデント発生時に不審なセッションを強制終了する際
- システムメンテナンス前に全ユーザーへの事前通知と強制ログアウトを行う際
- 同一アカウントの複数セッションを検知・整理する際

**主要な処理内容**：
1. オンラインユーザー一覧の表示（セッションID、ユーザー名、部門名、IP、ブラウザ、OS等）
2. 検索条件によるフィルタリング
3. 単一または複数セッションの強制ログアウト

**関連システム・外部連携**：Apache Shiroのセッション管理機能（OnlineSessionDAO）およびEhCacheと連携してセッション情報を管理する。

**権限による制御**：
- `monitor:online:view` - オンラインユーザー画面の閲覧
- `monitor:online:list` - オンラインユーザー一覧の取得
- `monitor:online:forceLogout` - 単一セッションの強制ログアウト
- `monitor:online:batchForceLogout` - 複数セッションの一括強制ログアウト

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 51 | オンラインユーザー一覧 | 主画面 | オンラインユーザー一覧表示と強制ログアウト処理 |

## 機能種別

データ検索 / セッション操作 / キャッシュ操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ipaddr | String | No | 検索対象のIPアドレス | 部分一致検索 |
| loginName | String | No | 検索対象のユーザー名 | 部分一致検索 |
| ids | String | No | 強制ログアウト対象のセッションID（カンマ区切り） | セッションID文字列 |

### 入力データソース

- 画面入力（検索条件）
- DBテーブル sys_user_online
- Shiroセッションストア（EhCache）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sessionId | String | セッションID |
| deptName | String | 部門名 |
| loginName | String | ユーザー名 |
| ipaddr | String | IPアドレス |
| loginLocation | String | ログイン地点 |
| browser | String | ブラウザ種類 |
| os | String | OS種類 |
| startTimestamp | Date | セッション開始日時 |
| lastAccessTime | Date | 最終アクセス日時 |
| expireTime | Long | セッション有効期限（ミリ秒） |
| status | OnlineStatus | オンライン状態（on_line/off_line） |

### 出力先

- 画面表示（TableDataInfo形式）

## 処理フロー

### 処理シーケンス

```
1. 一覧表示
   └─ ユーザーが検索条件を入力し、一覧取得リクエストを送信
   └─ Controllerが検索条件を受け取り、Serviceに委譲
   └─ ServiceがMapperを呼び出し、DBからオンラインセッション情報を取得
   └─ ページネーション情報と共に結果を返却

2. 強制ログアウト（単一/一括）
   └─ 対象のセッションIDリストを受け取る
   └─ 各セッションIDに対して以下を実行：
      └─ DBからセッション情報を取得
      └─ セッションが存在するか確認
      └─ 自分自身のセッションでないか確認
      └─ OnlineSessionDAOからセッションを削除
      └─ DBのステータスをoff_lineに更新
      └─ ユーザーキャッシュからセッション情報を削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|一覧表示| C[検索条件受付]
    C --> D[DB検索実行]
    D --> E[結果返却]

    B -->|強制ログアウト| F[セッションID受付]
    F --> G{各セッションを処理}
    G --> H[DBからセッション取得]
    H --> I{セッション存在?}
    I -->|No| J[エラー: ユーザー已下線]
    I -->|Yes| K[OnlineSessionDAO読込]
    K --> L{Shiroセッション存在?}
    L -->|No| M[エラー: ユーザー已下線]
    L -->|Yes| N{自分自身?}
    N -->|Yes| O[エラー: 自己強退不可]
    N -->|No| P[Shiroセッション削除]
    P --> Q[DBステータス更新]
    Q --> R[キャッシュ削除]
    R --> S{次のセッション?}
    S -->|Yes| G
    S -->|No| T[成功返却]

    E --> U[終了]
    J --> U
    M --> U
    O --> U
    T --> U
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-12-01 | 自己強制ログアウト禁止 | 自分自身のセッションは強制ログアウトできない | 強制ログアウト操作時 |
| BR-12-02 | オフラインセッション不可 | 既にオフラインのセッションは強制ログアウトできない | 強制ログアウト操作時 |
| BR-12-03 | 権限必須 | 強制ログアウトにはforceLogoutまたはbatchForceLogout権限が必要 | 強制ログアウト操作時 |
| BR-12-04 | セッション同期 | DBとShiroキャッシュの両方からセッションを削除する | 強制ログアウト時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | sys_user_online | SELECT | オンラインセッション一覧を取得 |
| 強制ログアウト | sys_user_online | UPDATE | ステータスをoff_lineに更新 |
| 強制ログアウト | sys_user_online | DELETE | オフラインセッションを物理削除（saveOnlineで実装） |

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

#### sys_user_online

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | session_id, dept_name, login_name, ipaddr, login_location, browser, os, start_timestamp, last_access_time, expire_time, status | WHERE条件で絞り込み | 一覧取得 |
| UPDATE | status | off_line | 強制ログアウト時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ユーザー已下線 | 対象セッションが存在しない場合 | 画面をリフレッシュ |
| - | 当前登録用戸無法強退 | 自分自身を強制ログアウトしようとした場合 | 他のセッションを選択 |
| - | 権限エラー | 必要な権限がない場合 | 適切な権限を付与 |

### リトライ仕様

特になし

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

- 強制ログアウト操作はセッション単位で処理
- 一括強制ログアウトで途中エラーが発生した場合、処理済みのセッションはログアウト完了

## パフォーマンス要件

- 一覧表示：1秒以内にレスポンス
- 強制ログアウト：対象セッション数に比例（1セッションあたり100ms以内目安）

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

- Apache Shiroによる権限制御
- 操作ログの記録（@Logアノテーション、BusinessType.FORCE）
- 自分自身の強制ログアウト禁止によるセルフロックアウト防止

## 備考

- セッション情報はShiroのOnlineSessionDAOによって管理される
- EhCacheを使用したセッションキャッシュ（SYS_USERCACHE）からもユーザー情報を削除
- 強制ログアウト後、対象ユーザーは次回リクエスト時にログイン画面へリダイレクトされる

---

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

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

### 推奨読解順序

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

まず、オンラインユーザーのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SysUserOnline.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java` | オンラインユーザーのエンティティクラス。OnlineStatus enum型のstatusフィールドに注目 |
| 1-2 | OnlineStatus.java | `ruoyi-common/src/main/java/com/ruoyi/common/enums/OnlineStatus.java` | オンライン状態の列挙型（on_line/off_line） |

**読解のコツ**: `OnlineStatus`はenum型で、オンライン（on_line）とオフライン（off_line）の2状態を管理する。デフォルト値は`on_line`。

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

コントローラーが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SysUserOnlineController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java` | 各エンドポイントの定義と権限設定 |

**主要処理フロー**:
1. **42-47行目**: 画面表示処理（GET /monitor/online）
2. **49-57行目**: 一覧取得処理（POST /monitor/online/list）
3. **59-87行目**: 一括強制ログアウト処理（POST /monitor/online/batchForceLogout）

#### Step 3: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ISysUserOnlineService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java` | サービスインターフェース定義 |
| 3-2 | SysUserOnlineServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java` | サービス実装 |

**主要処理フロー**:
- **37-40行目**: selectOnlineById - セッションID指定で取得
- **83-86行目**: saveOnline - セッション情報の保存・更新
- **93-97行目**: selectUserOnlineList - オンラインユーザー一覧取得
- **117-127行目**: removeUserCache - EhCacheからユーザーキャッシュを削除

#### Step 4: Shiroセッション管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | OnlineSessionDAO.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/OnlineSessionDAO.java` | Shiroセッションの永続化DAO |

**主要処理フロー**:
- `readSession()` - セッションIDからセッションオブジェクトを取得
- `delete()` - セッションを削除（強制ログアウト）

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

```
SysUserOnlineController
    │
    ├─ online()
    │      └─ 画面遷移（monitor/online/online）
    │
    ├─ list()
    │      └─ ISysUserOnlineService.selectUserOnlineList()
    │             └─ SysUserOnlineMapper.selectUserOnlineList()
    │
    └─ batchForceLogout()
           ├─ ISysUserOnlineService.selectOnlineById()
           │      └─ SysUserOnlineMapper.selectOnlineById()
           │
           ├─ OnlineSessionDAO.readSession()
           │      └─ EhCache/SessionManager
           │
           ├─ OnlineSessionDAO.delete()
           │      └─ EhCache/SessionManager
           │
           ├─ ISysUserOnlineService.saveOnline()
           │      └─ SysUserOnlineMapper.saveOnline()
           │
           └─ ISysUserOnlineService.removeUserCache()
                  └─ EhCacheManager.getCache()
                         └─ cache.remove()
```

### データフロー図

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

検索条件     ───▶ Controller         ───▶ TableDataInfo
(ipaddr,          ↓                        (rows, total)
 loginName)       Service
                  ↓
                  Mapper
                  ↓
                  sys_user_online

セッションID  ───▶ Controller         ───▶ AjaxResult
                  ↓                        (成功/エラー)
                  [1] selectOnlineById
                  ↓
                  [2] OnlineSessionDAO.readSession
                  ↓
                  [3] OnlineSessionDAO.delete
                  ↓
                  [4] saveOnline (status=off_line)
                  ↓
                  [5] removeUserCache
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SysUserOnlineController.java | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/` | コントローラー | HTTPリクエストのハンドリング |
| SysUserOnline.java | `ruoyi-system/src/main/java/com/ruoyi/system/domain/` | エンティティ | オンラインユーザーのデータモデル |
| ISysUserOnlineService.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/` | インターフェース | サービス層の契約定義 |
| SysUserOnlineServiceImpl.java | `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/` | サービス実装 | ビジネスロジック |
| SysUserOnlineMapper.java | `ruoyi-system/src/main/java/com/ruoyi/system/mapper/` | Mapper | データアクセス層インターフェース |
| SysUserOnlineMapper.xml | `ruoyi-system/src/main/resources/mapper/system/` | MyBatis XML | SQL定義 |
| OnlineSessionDAO.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/` | DAO | Shiroセッション永続化 |
| OnlineSession.java | `ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/session/` | エンティティ | Shiroセッションの拡張クラス |
| OnlineStatus.java | `ruoyi-common/src/main/java/com/ruoyi/common/enums/` | Enum | オンライン状態定義 |
