# 系统全面审计报告 — 2026-04-18 ## 审计环境 | 项目 | 值 | |---|---| | PostgreSQL | 18 (原生安装 D:\postgreSQL), 端口 5432 | | Redis | 未安装/未运行 (限流改为 fail-open 降级) | | 后端 | Axum 0.8, 端口 3000 | | 前端 | Vite 8, 端口 5174 | | 操作系统 | Windows 11 Pro | ## P0 — 严重问题(必须立即修复) ### 1. CRM 插件数据 403 Forbidden — ✅ 已修复 **现象**: 所有 CRM 数据页面(客户、联系人、沟通记录等)返回 403 错误,页面显示"加载数据失败"。 **根因**: CRM 插件在安装时正确注册了 9 条权限到 `permissions` 表(`erp-crm.customer.list` 等),但 **没有自动将这些权限分配给 admin 角色**。导致 JWT 中只有 `plugin.admin` 和 `plugin.list`,缺少 `erp-crm.*` 权限。 **修复**: 在 `erp-plugin/src/service.rs` 中新增 `grant_permissions_to_admin()` 函数,在 `install()` 和 `enable()` 中自动调用。修复后 CRM 客户列表 API 正常返回数据。 ### 2. CRM 插件启动恢复失败 — ✅ 已修复 **现象**: 后端日志 `Failed to recover plugin (initialize): 数据库错误: 关系 "plugin_erp_crm_inventory_item" 不存在` **根因**: CRM 插件的 `on_init` 回调尝试创建 `inventory_item` 实体的种子数据,但该表不存在。可能是 CRM 插件 WASM 代码中的实体定义与数据库迁移不匹配。 **影响**: 服务器重启后 CRM 插件恢复失败,`Plugins recovered: 0`。 **修复**: 通过升级 API 重新上传正确的 CRM WASM 二进制(22KB 替换错误的 110KB 测试插件)。修复后插件正常恢复并运行。 ### 3. 首页统计数据卡片永久 Loading **现象**: 工作台首页 4 个统计卡片(用户总数、角色数量、流程实例、未读消息)显示 loading 状态(`busy` 属性),数字不显示。 **根因**: 首页统计卡片使用 `useCountUp` 动画但依赖数据加载,数据加载可能失败或 API 返回格式不匹配。 ### 4. 插件 API 路由不支持字符串 ID **现象**: `/api/v1/plugins/erp-crm/customer` 返回 `UUID parsing failed`。 **根因**: 后端路由定义 `Path<(Uuid, String)>`,要求 `plugin_id` 必须是 UUID 格式。但插件的 manifest ID 是字符串(如 `erp-crm`)。 **影响**: 直接用 manifest ID 调用 API 不行,必须先查 UUID。前端已绕过此问题(使用 UUID),但 API 设计不够友好。 ## P1 — 高优先级问题 ### 5. XSS: 显示名未转义存储 **现象**: `POST /api/v1/users` 时 `display_name` 字段可以存储 ``,API 返回原样值。 **评估**: React 框架自动转义防止了前端 XSS。但数据库中存储了原始 HTML,如果有其他客户端(如邮件、导出 PDF 等)不转义渲染,仍存在风险。 **建议**: 后端入库时 strip HTML tags 或 escape。 ### 6. 重复用户名检测缺失 **现象**: `POST /api/v1/users` 用 `audit_test_user` 创建两次,第二次也返回 `success: true`,没有报重复错误。 **评估**: 第二次创建返回的 `id` 不同但 `username` 相同,说明用户名唯一性约束可能没生效。 ### 7. 消息模板 API 返回空 **现象**: `GET /api/v1/messages/templates` 返回空 body(非 JSON)。 **根因**: 可能数据库无模板数据,且空列表情况下序列化异常。 ### 8. 主题 API 返回空 **现象**: `GET /api/v1/config/theme` 返回空 body。 ### 9. `roles/permissions` 路由冲突 — ✅ 已修复 **现象**: `GET /api/v1/roles/permissions` 返回 UUID 解析错误。 **根因**: 路由 `GET /roles/{id}` 把 `permissions` 当成 UUID 解析了。 **修复**: 在 `erp-auth/src/module.rs` 中,在 `/roles/{id}` 之前注册 `/roles/permissions` 精确匹配路由。修复后返回 64 条权限数据。 ## P2 — 中优先级问题 ### 10. CRM 插件恢复后 Plugin recovered: 0 后端日志显示插件加载成功但 recovery 报 0。on_init 失败导致插件状态变为 error,但实际插件 WASM 已加载到内存。 ### 11. 创建用户时中文 display_name 解析失败 `POST /api/v1/users` 带 `display_name` 含中文字符时,返回 `invalid unicode code point`。可能与 curl 的编码有关而非后端 bug,需要进一步验证。 ### 12. 菜单数据为空 `GET /api/v1/config/menus` 返回空数组。系统侧边栏菜单是前端硬编码的,后端菜单配置未使用。 ### 13. 数据字典为空 `GET /api/v1/config/dictionaries` 返回空。这是正常的(未创建字典数据)。 ## P3 — 低优先级 / 代码质量 ### 14. 前端死代码 - `src/pages/plugins/graph/` 6 个文件完全未使用 - `src/hooks/` 下 4 个 Hook 未被任何组件引用(useDarkMode, useDebouncedValue, usePaginatedData, useApiRequest) - `useCountUp` 在 3 处重复定义 ### 15. i18n 已配置但完全未使用 i18next 已初始化,翻译文件有 30 个 key,但所有页面组件硬编码中文。 ### 16. 暗色模式检测逻辑重复 20+ 次 `const isDark = token.colorBgContainer === '#111827'` 在 20+ 组件中重复,已有 `useDarkMode` Hook 但未使用。 ### 17. antd 废弃 API 警告 - `Drawer` 的 `width` 属性已废弃 - `Modal` 的 `destroyOnClose` 已废弃 - `message` 静态方法无法消费 context ## 安全测试结果 | 测试项 | 结果 | |---|---| | 无 token 访问 | 401 Unauthorized | | 错误 token | 401 Unauthorized | | 错误密码登录 | 401 Unauthorized | | 空请求体登录 | 反序列化错误(非 500) | | 短密码验证 | 400 Bad Request + 详细验证信息 | | SQL 注入(用户名) | JSON 解析失败(被拦截) | | XSS(显示名) | 存储了原始 HTML(需后端过滤) | | 权限不足操作 | 403 Forbidden | ## 正常工作的功能 - 登录/登出/Token 刷新 - 用户 CRUD(创建/列表/删除) - 角色 CRUD + 权限查看 - 组织架构三栏管理 - 工作流定义列表/待办任务 - 消息列表/已读/未读计数 - 审计日志记录 - 插件管理(上传/启用/停用) - 系统设置 Tab 页(字典/语言/菜单/编号/主题/参数/审计/密码) - OpenAPI 文档端点 ## 下一步工作建议 1. **P0-1**: 修复插件权限自动分配给 admin 角色 2. **P0-2**: 修复 CRM 插件 on_init 中 inventory_item 表不存在的问题 3. **P0-3**: 修复首页统计卡片数据加载 4. **P1-5**: 后端 display_name HTML 过滤 5. **P1-6**: 用户名唯一性约束 6. **P1-9**: 修复 roles/permissions 路由冲突 7. 更新所有相关文档(wiki/插件系统文档)