kindergarten_java/docs/dev-logs/2026-03-24.md
En 6f47a07401 docs(开发日志): 补充 RSA 加密功能文档和细节调整
- 追加 RSA 密码加密传输的完整实现文档
- 操作日志相关细节调整

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:08:29 +08:00

233 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 开发日志 - 2026-03-24
## 工作内容
### 租户管理详情页字段补充
#### 背景
超管端租户管理查看详情时,前端页面期望展示以下数据:
1. 使用统计:教师数、学生数、**班级数**、**授课数**
2. **最近教师列表**(姓名、手机号、状态)
3. **最近学生列表**(姓名、性别、阅读数)
4. **最近班级列表**(名称、年级、学生数)
#### 修改内容
**1. 后端 DTO 扩展** (`TenantResponse.java`)
- 新增 `classCount` 字段 - 班级数量
- 新增 `lessonCount` 字段 - 授课数量
- 新增 `teachers` 字段 - 最近教师列表(`TeacherItem` 内部类)
- 新增 `students` 字段 - 最近学生列表(`StudentItem` 内部类)
- 新增 `classes` 字段 - 最近班级列表(`ClassItem` 内部类)
**2. 后端 Service 层修改** (`TenantServiceImpl.java`)
- 新增 `getTenantDetail()` 方法 - 返回完整的租户详情响应
- 新增 `buildTenantResponse()` 方法 - 构建包含统计信息和列表的响应数据
- 新增 Mapper 依赖注入:
- `ClazzMapper` - 班级数据访问
- `StudentRecordMapper` - 学生阅读记录访问
- `StudentClassHistoryMapper` - 学生班级关联访问
**3. 后端 Controller 层修改** (`AdminTenantController.java`)
- 修改 `getTenant()` 方法调用 `tenantService.getTenantDetail(id)` 返回完整详情
**4. 前端类型定义更新** (`admin.ts`)
- 扩展 `TenantDetail` 接口:
- 添加 `classCount``lessonCount` 字段
- `students[].classId` 改为可选字段(因为学生班级关联是可选的)
**5. 前端详情组件更新** (`TenantListView.vue`)
- 修改统计数据显示使用 `detailData.classCount``detailData.lessonCount`
#### 技术细节
1. **学生班级 ID 获取**:由于学生实体没有直接的 `classId` 字段,通过 `student_class_history` 关联表查询学生当前所在的班级 ID。
2. **班级学生数统计**:通过 `student_class_history` 表查询每个班级的 ACTIVE 状态学生数量。
3. **学生阅读次数统计**:通过 `student_record` 表统计每个学生的记录数。
4. **教师授课次数统计**:通过 `schedule_plan` 表统计每个教师的排课数量。
#### 验证步骤
1. ✅ 后端编译成功
2. ⏳ 启动服务测试(待用户验证)
#### 文件清单
| 文件 | 修改内容 |
|------|---------|
| `TenantResponse.java` | 新增字段和内部类 |
| `TenantServiceImpl.java` | 新增方法和 Mapper 依赖 |
| `AdminTenantController.java` | 修改详情查询方法 |
| `admin.ts` | 扩展类型定义 |
| `TenantListView.vue` | 更新详情展示 |
---
## 工作内容 - 学校端操作日志请求参数与接口展示
### 背景
在学校端操作日志页面,需要记录并返回以下三个信息:
1. **操作人** - 谁执行的操作(已有 `userId`、`userRole`
2. **请求参数** - 操作时传入的参数(`requestParams`
3. **请求接口** - 执行的具体 API 接口路径(`requestUri`
当前后端已通过 `LogAspect` 自动记录这些信息到数据库,但未返回给前端展示。
### 修改内容
#### 1. 数据库迁移
**文件**: `V50__add_request_uri_to_operation_log.sql`
- 添加 `request_uri` 字段 - VARCHAR(500),记录请求接口路径
#### 2. 后端实体修改
**文件**: `OperationLog.java`
- 新增 `requestUri` 字段
#### 3. 后端切面修改
**文件**: `LogAspect.java`
-`before()` 方法中记录 `requestURI`
#### 4. 后端 Response DTO 修改
**文件**: `OperationLogResponse.java`
- 新增 `requestParams` 字段 - 请求参数 JSON
- 新增 `requestUri` 字段 - 请求接口路径
#### 5. 后端 Controller 修改
**文件**: `SchoolOperationLogController.java`
-`convertToResponse()` 方法中添加字段映射
#### 6. 前端类型定义更新
**文件**: `school.ts`
- `OperationLog` 接口添加 `requestParams``requestUri` 字段
#### 7. 前端页面修改
**文件**: `OperationLogView.vue`
- 详情弹窗新增"请求接口"展示项
- 详情弹窗新增"请求参数"展示项JSON 格式化)
### 验证步骤
1. ✅ 后端编译成功
2. ⏳ 数据库迁移待执行
3. ⏳ 启动服务测试
### 文件清单
| 文件 | 修改内容 |
|------|---------|
| `V50__add_request_uri_to_operation_log.sql` | 新增数据库迁移 |
| `OperationLog.java` | 新增 `requestUri` 字段 |
| `LogAspect.java` | 记录 `requestURI` |
| `OperationLogResponse.java` | 新增返回字段 |
| `SchoolOperationLogController.java` | 字段映射 |
| `school.ts` | 类型定义更新 |
| `OperationLogView.vue` | 详情展示新增字段 |
---
## 工作内容 - RSA 密码加密传输实现
### 背景
当前登录系统密码明文传输,存在安全风险。需要实现 RSA 非对称加密,确保密码在传输过程中加密。
### 实现方案
使用简化 RSA 方案:
1. 后端生成 RSA 密钥对,提供公钥获取接口
2. 前端登录前获取公钥,用 RSA 加密密码
3. 后端用私钥解密密码,继续原有登录流程
### 修改内容
#### 后端部分
**1. 新建 RSA 加密工具类** (`RsaEncryptionUtil.java`)
- 生成 RSA 2048 位密钥对
- 提供公钥获取方法
- 提供私钥解密方法
- 支持密钥版本管理
- 密钥仅保存在内存中,不持久化
**2. 新建密钥轮换任务** (`RsaKeyRotationTask.java`)
- 每月 1 日凌晨 2 点自动更换 RSA 密钥
- 使用 `@Scheduled(cron = "0 0 2 1 * ?")` 定时执行
- 支持日志记录密钥版本变更
**3. 新建加密登录请求 DTO** (`EncryptedLoginRequest.java`)
- `username` - 登录账号(明文)
- `encryptedPassword` - RSA 加密后的密码Base64
- `role` - 登录角色
- `keyVersion` - 密钥版本号(可选)
**4. 新建公钥响应 DTO** (`PublicKeyResponse.java`)
- `publicKey` - RSA 公钥Base64
- `keyVersion` - 当前密钥版本号
**5. 修改认证控制器** (`AuthController.java`)
- 新增 `GET /api/v1/auth/public-key` - 获取 RSA 公钥
- 新增 `POST /api/v1/auth/login/encrypted` - 加密登录接口
- 注入 `RsaEncryptionUtil` 进行加解密操作
#### 前端部分
**6. 添加依赖** (`package.json`)
- 添加 `jsencrypt@^3.3.2` - RSA 加密库
**7. 新建加密工具** (`encryption.ts`)
- `rsaEncrypt(data, publicKey)` - RSA 加密函数
- 导出 `PublicKeyResponse``EncryptedLoginParams` 类型
**8. 修改认证 API** (`auth.ts`)
- 新增 `getPublicKey()` - 获取公钥
- 新增 `loginEncrypted(params)` - 加密登录
**9. 修改用户 Store** (`user.ts`)
- 修改 `login()` 函数,改为 RSA 加密流程:
1. 获取 RSA 公钥
2. 加密密码
3. 调用加密登录接口
### 登录流程变更
**原流程**
```
明文密码 → POST /api/v1/auth/login → 后端验证
```
**新流程**
```
1. GET /api/v1/auth/public-key → 获取 RSA 公钥
2. 前端用公钥加密密码
3. POST /api/v1/auth/login/encrypted → 后端私钥解密 → 验证登录
```
### 安全特性
- RSA 2048 位加密,安全性足够
- **密钥每月自动更换** - 每月 1 日凌晨 2 点自动更换
- 密钥版本管理 - 便于排查问题
- 私钥仅保存在后端内存中,不持久化
- 必须配合 HTTPS 使用
### 验证步骤
1. 安装前端依赖:`cd reading-platform-frontend && npm install`
2. 启动后端服务,测试 `GET /api/v1/auth/public-key` 返回公钥
3. 启动前端,打开浏览器开发者工具
4. 登录时检查 Network 面板:
- `/v1/auth/public-key` 返回公钥
- `/v1/auth/login/encrypted` 请求的 `encryptedPassword` 为密文
5. 验证登录功能正常
### 文件清单
| 文件 | 操作 | 说明 |
|------|------|------|
| `RsaEncryptionUtil.java` | 新建 | RSA 加密工具类 |
| `RsaKeyRotationTask.java` | 新建 | 密钥轮换定时任务 |
| `EncryptedLoginRequest.java` | 新建 | 加密登录请求 DTO |
| `PublicKeyResponse.java` | 新建 | 公钥响应 DTO |
| `AuthController.java` | 修改 | 添加公钥和加密登录接口 |
| `package.json` | 修改 | 添加 jsencrypt 依赖 |
| `encryption.ts` | 新建 | 前端 RSA 加密工具 |
| `auth.ts` | 修改 | 添加加密登录 API |
| `user.ts` | 修改 | 使用 RSA 加密登录 |