# セキュリティ設計書

## 概要

本ドキュメントは、RuoYiシステムのセキュリティ設計について記載する。本システムはApache Shiroフレームワークを基盤とした認証・認可機能を実装し、XSS/CSRF対策、データアクセス制御、監査ログ機能を提供する。

## 認証設計

### 認証方式

本システムはApache Shiroフレームワークを使用したフォームベース認証を採用している。

| 項目 | 内容 |
| --- | --- |
| 認証フレームワーク | Apache Shiro |
| 認証方式 | ユーザー名・パスワードによるフォーム認証 |
| パスワードハッシュ | MD5（ユーザー名 + パスワード + Salt） |
| 認証処理クラス | `UserRealm.doGetAuthenticationInfo()` |
| ログインサービス | `SysLoginService.login()` |

**パスワード暗号化方式:**
```java
// SysPasswordService.encryptPassword()
new Md5Hash(loginName + password + salt).toHex()
```

**ログイン失敗時の制御:**

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| 最大試行回数 | 5回 | `user.password.maxRetryCount`で設定 |
| ロックアウト | キャッシュベース | EhCacheで管理 |

### セッション管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| セッション有効期限 | 30分（デフォルト） | `shiro.session.expireTime`で設定 |
| セッション固定化対策 | 実装済み | Shiroのセッション管理機能で対応 |
| セッション検証間隔 | 10分 | `shiro.session.validationInterval`で設定 |
| 同一ユーザー最大セッション数 | 無制限（-1） | `shiro.session.maxSession`で設定可能 |
| セッションID URL書き換え | 無効 | `setSessionIdUrlRewritingEnabled(false)` |
| セッション永続化 | データベース | `SysUserOnline`テーブルに保存 |

**セッション管理クラス:**
- `OnlineWebSessionManager`: セッションの有効期限管理、過期セッションの削除
- `OnlineSessionDAO`: セッションのデータベース永続化
- `KickoutSessionFilter`: 同一ユーザーの多重ログイン制御

### 記憶機能（Remember Me）

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| 有効/無効 | 設定可能 | `shiro.rememberMe.enabled`で制御 |
| Cookie有効期限 | 30日 | `shiro.cookie.maxAge`で設定 |
| 暗号化方式 | AES 128bit | `CipherUtils.generateNewKey(128, "AES")` |
| Cookie HttpOnly | true | セキュリティ強化 |

### 検証コード（CAPTCHA）

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| 有効/無効 | true（デフォルト） | `shiro.user.captchaEnabled`で設定 |
| 検証タイプ | 数学計算（math） | `shiro.user.captchaType`で設定（char/math） |
| 検証フィルター | `CaptchaValidateFilter` | ログイン・登録時に適用 |

## 認可設計

### 権限体系

本システムはRBAC（Role-Based Access Control）モデルを採用している。

| ロール | 権限 | 説明 |
| --- | --- | --- |
| admin | `*:*:*` | 全権限を持つ管理者ロール |
| 一般ロール | メニュー権限に基づく | ロールに紐づくメニュー権限で制御 |

**データスコープ（データ権限）:**

| スコープ | 値 | 説明 |
| --- | --- | --- |
| 全データ | 1 | 全てのデータにアクセス可能 |
| カスタム | 2 | カスタム定義のデータ範囲 |
| 所属部門 | 3 | 自部門のデータのみ |
| 部門及び配下 | 4 | 自部門と配下部門のデータ |
| 本人のみ | 5 | 自分自身のデータのみ |

### アクセス制御

**URLベースのアクセス制御:**

Shiro FilterChainで制御される。

| パターン | フィルター | 説明 |
| --- | --- | --- |
| 静的リソース（css/js/img等） | `anon` | 匿名アクセス許可 |
| `/login`, `/register` | `anon,captchaValidate` | 匿名アクセス + CAPTCHA検証 |
| `/logout` | `logout` | ログアウト処理 |
| `/**`（その他） | `user,kickout,onlineSession,syncOnlineSession,csrfValidateFilter` | 認証必須 |

**メソッドレベルのアクセス制御:**

Apache Shiroアノテーションによる権限チェック。

```java
@RequiresPermissions("system:role:list")
public TableDataInfo list(SysRole role) { ... }
```

| アノテーション | 用途 |
| --- | --- |
| `@RequiresPermissions` | 特定権限の要求 |
| `@RequiresRoles` | 特定ロールの要求 |

**データスコープ制御:**

`DataScopeAspect`によりSQLレベルでのデータアクセス制御を実装。

```java
@DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUserList(SysUser user) { ... }
```

## 通信セキュリティ

| 項目 | 対策 |
| --- | --- |
| HTTPS | アプリケーション設定に依存（本システムでは設定なし） |
| HSTS | 未設定（インフラ層で対応推奨） |

**注記:** HTTPS/HSTS設定はWebサーバー（Nginx/Apache等）での設定を推奨する。

## データセキュリティ

### 暗号化

| 対象 | 暗号化方式 |
| --- | --- |
| 通信 | アプリケーション外（HTTPS推奨） |
| パスワード保存 | MD5ハッシュ（Salt付き） |
| Remember Me Cookie | AES 128bit |
| セッション暗号化キー | 設定可能（`shiro.cookie.cipherKey`） |

### 機密情報管理

**ログ出力時の機密情報除外:**

`LogAspect`で以下のフィールドをログ出力から除外。

```java
public static final String[] EXCLUDE_PROPERTIES = {
    "password", "oldPassword", "newPassword", "confirmPassword"
};
```

**IPブラックリスト:**

システム設定（`sys.login.blackIPList`）でログイン禁止IPを管理。

## 入出力対策

| 脅威 | 対策 |
| --- | --- |
| XSS | `XssFilter`によるHTMLタグ除去・エスケープ |
| SQLインジェクション | MyBatisパラメータバインディング（`#{}`構文） |
| CSRF | `CsrfValidateFilter`によるトークン検証（設定で有効化可能） |
| 重複送信 | `RepeatSubmitInterceptor`による制御 |

### XSS対策

**XSSフィルター設定（application.yml）:**

```yaml
xss:
  enabled: true
  excludes: /system/notice/*
  urlPatterns: /system/*,/monitor/*,/tool/*
```

**フィルター処理:**

| クラス | 役割 |
| --- | --- |
| `XssFilter` | リクエストの振り分け、除外URL判定 |
| `XssHttpServletRequestWrapper` | パラメータ値のサニタイズ |
| `HTMLFilter` | HTMLタグのホワイトリストフィルタリング |
| `EscapeUtil` | 特殊文字のエスケープ処理 |

**許可されるHTMLタグ:**
- `<a>`: href, target属性
- `<img>`: src, width, height, alt属性
- `<b>`, `<strong>`, `<i>`, `<em>`: 属性なし

**許可されるプロトコル:** http, https, mailto

### CSRF対策

**CSRF設定（application.yml）:**

```yaml
csrf:
  enabled: false  # デフォルト無効
  whites: /druid
```

**CSRF検証処理:**
- POSTリクエストのみ検証
- HTTPヘッダー`X-CSRF-TOKEN`でトークン送信
- セッション内トークンとの照合

### SQLインジェクション対策

**対策方式:** MyBatisのパラメータバインディング

```xml
<!-- 安全な記述例 -->
<if test="loginName != null and loginName != ''">
    AND login_name like concat('%', #{loginName}, '%')
</if>
```

**DataScopeでの注入防止:**

```java
// DataScopeAspect.clearDataScope()
// SQL組み立て前にparams.dataScopeをクリアして注入を防止
baseEntity.getParams().put(DATA_SCOPE, "");
```

## 監査ログ

| ログ種別 | 記録内容 | 保持期間 |
| --- | --- | --- |
| 操作ログ（sys_oper_log） | 操作者、操作内容、リクエストパラメータ、処理結果、実行時間、IPアドレス | アプリケーション設定による |
| ログインログ（sys_logininfor） | ユーザー名、ログイン状態、IPアドレス、ブラウザ、OS、メッセージ、ログイン日時 | アプリケーション設定による |

### 操作ログ

**記録項目（SysOperLog）:**

| 項目 | 説明 |
| --- | --- |
| title | 操作タイトル（モジュール名） |
| businessType | 操作種別（0:その他 1:新規 2:更新 3:削除 等） |
| method | 実行メソッド |
| requestMethod | HTTPメソッド |
| operatorType | 操作者種別 |
| operName | 操作者名 |
| deptName | 部門名 |
| operUrl | リクエストURL |
| operIp | 操作元IP |
| operParam | リクエストパラメータ（機密情報除外） |
| jsonResult | レスポンス結果 |
| status | 処理状態 |
| errorMsg | エラーメッセージ |
| costTime | 処理時間（ミリ秒） |

**ログ記録アノテーション:**

```java
@Log(title = "用户管理", businessType = BusinessType.INSERT)
public AjaxResult add(@Validated @RequestBody SysUser user) { ... }
```

### ログインログ

**記録項目（SysLogininfor）:**

| 項目 | 説明 |
| --- | --- |
| loginName | ログインユーザー名 |
| status | ログイン状態（成功/失敗） |
| ipaddr | IPアドレス |
| loginLocation | ログイン場所 |
| browser | ブラウザ |
| os | OS |
| msg | メッセージ |
| loginTime | ログイン日時 |

## 備考

### セキュリティ上の注意点

1. **パスワードハッシュ:** 現在MD5を使用しているが、より安全なbcrypt等への移行を推奨
2. **CSRF保護:** デフォルトで無効のため、本番環境では有効化を推奨
3. **HTTPS:** アプリケーションレベルでの設定はないため、リバースプロキシ等での設定が必要
4. **Remember Me暗号化キー:** 未設定の場合は起動ごとに自動生成されるため、クラスタ環境では固定キーの設定が必要

### 関連設定ファイル

| ファイル | 内容 |
| --- | --- |
| `application.yml` | Shiro、XSS、CSRF設定 |
| `ehcache-shiro.xml` | セッションキャッシュ設定 |
| `ShiroConfig.java` | Shiro設定クラス |
| `FilterConfig.java` | XSSフィルター設定 |
