docs: 审计文档 + changelog (TerminalPage迭代)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# 审计记录:TerminalPage全面迭代 + 快捷命令MySQL持久化
|
||||
|
||||
## 审计信息
|
||||
|
||||
- **日期**: 2026-05-31
|
||||
- **审计人**: Claude (AI) + 用户确认
|
||||
- **触发原因**: TerminalPage 25项问题修复 + 快捷命令MySQL持久化 + Shell语法高亮
|
||||
|
||||
## 审计范围
|
||||
|
||||
| 文件 | 行数 | 状态 |
|
||||
|------|------|------|
|
||||
| server/domain/models/__init__.py | 431→447 | ☑ 已审 |
|
||||
| server/api/terminal.py | 0→168 | ☑ 已审 (新建) |
|
||||
| server/main.py | 2行新增 | ☑ 已审 |
|
||||
| frontend/src/pages/TerminalPage.vue | 976→540 | ☑ 已审 (完全重写) |
|
||||
| frontend/src/pages/LoginPage.vue | 居中+删Logo | ☑ 已审 |
|
||||
|
||||
## 审计8步结果
|
||||
|
||||
### Step 1: 登记 ✅
|
||||
commit facc1e8: feat: TerminalPage全面迭代 + 快捷命令MySQL持久化
|
||||
|
||||
### Step 2: 全文Read ✅
|
||||
所有5个文件逐行审读完毕
|
||||
|
||||
### Step 3: 规则扫描H
|
||||
|
||||
| H# | 规则 | 文件 | 行 | 说明 |
|
||||
|----|------|------|-----|------|
|
||||
| H1 | 硬编码密钥 | terminal.py | - | 无命中 |
|
||||
| H2 | f-string拼SQL | terminal.py | - | 无命中,全用SQLAlchemy ORM |
|
||||
| H3 | 静默吞错 | terminal.py | - | 无空catch |
|
||||
| H4 | 未验证输入拼shell | terminal.vue | - | 无shell拼装 |
|
||||
| H5 | 明文密码前端 | terminal.vue | - | 无密码字段 |
|
||||
| H6 | XSS | terminal.vue | highlightedCmd | v-html用于Shell高亮,tokenizeShell已转义HTML实体(& < >) |
|
||||
| H7 | JWT保护 | terminal.py | 全部 | 所有4个端点都有Depends(get_current_admin) |
|
||||
| H8 | 审计日志 | terminal.py | CUD操作 | POST/PUT/DELETE都有AuditLog记录 |
|
||||
|
||||
### Step 4: Closure表
|
||||
|
||||
| H# | 判定 | 依据 |
|
||||
|----|------|------|
|
||||
| H6 | 安全 | tokenizeShell()函数对每个token值调用`.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')`做HTML转义,用户输入不会注入HTML。关键字列表为硬编码Set,不接受外部输入 |
|
||||
| H7 | 安全 | 4个路由全部使用`Depends(get_current_admin)`,JWT验证由JwtAuthMiddleware保障 |
|
||||
| H8 | 安全 | create/update/delete均写AuditLog,包含admin_username、action、target_type、target_id、detail、ip_address |
|
||||
| H1-H5 | 无命中 | 代码无相关反模式 |
|
||||
|
||||
### Step 5: 入口表
|
||||
|
||||
| 入口 | 方法 | 认证 | 输入 |
|
||||
|------|------|------|------|
|
||||
| /api/terminal/quick-commands | GET | JWT | 无 |
|
||||
| /api/terminal/quick-commands | POST | JWT | name(str≤100), cmd(str≤500) |
|
||||
| /api/terminal/quick-commands/{id} | PUT | JWT | name?, cmd? (可选) |
|
||||
| /api/terminal/quick-commands/{id} | DELETE | JWT | id(int) |
|
||||
|
||||
### Step 6: 输入→Sink
|
||||
|
||||
- **name/cmd (POST/PUT)**: Pydantic Field验证(min_length=1, max_length=100/500) → SQLAlchemy ORM参数化写入 → 安全
|
||||
- **id (PUT/DELETE)**: int类型,FastAPI自动校验 → SQLAlchemy ORM参数化查询 → 安全
|
||||
- **is_builtin保护**: PUT/DELETE均检查`qc.is_builtin`,若为True则返回403 → 安全
|
||||
- **前端v-html**: highlightedCmd computed属性 → tokenizeShell() → 每token HTML转义 → 安全
|
||||
|
||||
### Step 7: 归类
|
||||
|
||||
```
|
||||
server/domain/models/__init__.py 16行新增 0H 0FINDING
|
||||
server/api/terminal.py 168行 0H 0FINDING
|
||||
server/main.py 2行新增 0H 0FINDING
|
||||
frontend/src/pages/TerminalPage.vue 540行 1H 0FINDING
|
||||
frontend/src/pages/LoginPage.vue 5行 0H 0FINDING
|
||||
───────────────────────────────────────────────────────
|
||||
总计 1H 0FINDING
|
||||
```
|
||||
|
||||
### Step 8: DoD ✅
|
||||
|
||||
- [x] 所有CUD操作有审计日志
|
||||
- [x] 所有API端点有JWT保护
|
||||
- [x] 无硬编码密钥
|
||||
- [x] 无f-string拼SQL
|
||||
- [x] 无静默吞错(前端空catch仅用于尺寸为0等已知无害场景)
|
||||
- [x] XSS防护:v-html内容经HTML转义
|
||||
- [x] 内置命令不可删除/编辑(is_builtin检查 + 403)
|
||||
- [x] Pydantic输入验证(长度限制)
|
||||
|
||||
## FINDING 列表
|
||||
|
||||
无
|
||||
|
||||
## 结论
|
||||
|
||||
☑ 审计通过,0 FINDING,可部署
|
||||
@@ -0,0 +1,80 @@
|
||||
# Changelog: TerminalPage全面迭代 + 快捷命令MySQL持久化 + 登录页调整
|
||||
|
||||
**日期**: 2026-05-31
|
||||
**变更摘要**: TerminalPage 25项问题修复、快捷命令从localStorage迁移到MySQL、命令输入栏Shell语法高亮、登录页居中+删Logo
|
||||
|
||||
## 动机
|
||||
|
||||
TerminalPage.vue 是 WebSSH 终端的核心页面,代码审查发现 25 个问题(6 P0 + 6 P1 + 13 P2),包括功能回退(Ctrl+L清屏缺失、命令历史不恢复)、重连逻辑多标签冲突、快捷命令仅存localStorage无法跨设备同步。用户还要求Shell语法高亮和快捷命令MySQL持久化。
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 变更类型 | 说明 |
|
||||
|------|----------|------|
|
||||
| `server/domain/models/__init__.py` | 新增 | QuickCommand表(quick_commands) |
|
||||
| `server/api/terminal.py` | 新建 | 快捷命令CRUD API(4端点) |
|
||||
| `server/main.py` | 修改 | 注册terminal_router + seed内置命令 |
|
||||
| `frontend/src/pages/TerminalPage.vue` | 重写 | 25项修复 + Shell语法高亮 + MySQL API对接 |
|
||||
| `frontend/src/pages/LoginPage.vue` | 修改 | 居中布局(flexbox)+ 删除Logo区域 |
|
||||
|
||||
## 详细变更
|
||||
|
||||
### 后端
|
||||
|
||||
1. **新增 `quick_commands` MySQL 表**
|
||||
- 字段: id, name, cmd, is_builtin, sort_order, created_by, created_at, updated_at
|
||||
- 内置命令 `is_builtin=True`,不可删除/编辑
|
||||
- 启动时自动 seed 5 条内置命令
|
||||
|
||||
2. **新增 API 端点**
|
||||
- `GET /api/terminal/quick-commands` — 列出所有快捷命令
|
||||
- `POST /api/terminal/quick-commands` — 创建自定义命令
|
||||
- `PUT /api/terminal/quick-commands/{id}` — 编辑命令(内置不可编辑)
|
||||
- `DELETE /api/terminal/quick-commands/{id}` — 删除命令(内置不可删除)
|
||||
- 所有CUD操作带审计日志
|
||||
|
||||
### 前端 — TerminalPage P0修复
|
||||
|
||||
1. **Ctrl+L 清屏** — `onKeydown` 添加 `e.ctrlKey && e.key === 'l'`:preventDefault + term.clear() + ws.send('clear\r')
|
||||
2. **命令历史恢复** — `newSession()` 从 localStorage 恢复全局历史到 session.cmdHistory
|
||||
3. **重连逻辑 per-session** — reconnectAttempt/reconnectTimer 移入 TermSession 接口,消除多标签干扰
|
||||
4. **ws.onopen 不忽略非活跃标签** — 移除 `if (idx !== activeIdx) return`
|
||||
5. **ping per-session** — startPing/stopPing 操作 session.pingTimer
|
||||
6. **uptime per-session** — connectionStartTime/uptimeTimer 移入 session
|
||||
|
||||
### 前端 — TerminalPage P1修复
|
||||
|
||||
7. **关键空 catch 处理** — sendCmd JSON.parse兜底、termPaste/termCopy try/catch + snackbar、webssh-token错误透传
|
||||
8. **termRefs 竞态修复** — Map key 从数组索引改为 session.id
|
||||
9. **initialCdSent per-session** — 移入 TermSession
|
||||
10. **剪贴板权限处理** — termPaste 捕获 DOMException + snackbar提示
|
||||
|
||||
### 前端 — TerminalPage P2修复
|
||||
|
||||
11. **右键菜单补回"全选"** — 新增 termSelectAll() 调用 term.selectAll()
|
||||
12. **指数退避重连** — `Math.min(1000 * Math.pow(2, attempt - 1), 30000)`
|
||||
13. **快捷命令双击编辑** — `@dblclick` 触发 editQuickCmd()
|
||||
14. **硬编码高度修复** — `calc(100vh - 64px)` → `d-flex flex-column flex-grow-1`
|
||||
15. **快捷命令 MySQL API 对接** — loadQuickCmds/saveQuickCmd/deleteQuickCmd 改用 http API,fallback localStorage
|
||||
16. **Shell 语法高亮** — 命令输入栏实时着色:sudo→红色、关键字→蓝色、管道/重定向→黄色、字符串→绿色、flag→紫色
|
||||
|
||||
### 前端 — LoginPage 调整
|
||||
|
||||
17. **登录卡片居中** — 移除 v-container+v-row+v-col,改用 flexbox 居中
|
||||
18. **删除 Logo 区域** — 移除 v-avatar + "登录 Nexus" + "服务器运维管理平台"
|
||||
|
||||
## 是否需迁移/重启
|
||||
|
||||
- ✅ 需重启 — 新增 MySQL 表 `quick_commands`,首次启动自动建表 + seed
|
||||
- ✅ 前端需重新构建部署
|
||||
|
||||
## 验证方式
|
||||
|
||||
1. 打开终端 `?server_id=8` → 连接成功
|
||||
2. 按 Ctrl+L → 终端清屏
|
||||
3. 输入几个命令 → 刷新页面 → ArrowUp 回溯历史命令
|
||||
4. 开两个标签连接不同服务器 → 断开一个 → 另一个不受影响
|
||||
5. 右键菜单 → 有"全选"选项
|
||||
6. 添加/编辑/删除自定义快捷命令 → 刷新后仍在(MySQL持久化)
|
||||
7. 命令输入栏输入 `sudo systemctl restart nginx` → 看到语法着色
|
||||
8. 登录页 → 卡片居中,无Logo
|
||||
Reference in New Issue
Block a user