unis_crm/系统测试报告-20260903.md

142 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# UNIS CRM 系统测试报告
- **测试日期**2026-09-03
- **测试环境**:本机开发环境(后端 127.0.0.1:8080CRM 前端 3000/3002数据库/Redis 192.168.124.202
- **测试账号**:管理员 admin_crm (userId=19)、普通账号 13752913297/周瑾·部门领导 (userId=20)
- **测试方式**API 全量扫描 + 越权/安全专项测试 + 后端单元测试 + 前端构建验证
---
## 一、总体结论
系统**核心业务功能基本正常**(登录/刷新、工作台、商机管理、渠道拓展、归属转移、签到/日报、经营分析、导出等主流程均可跑通,错误提示友好,前端两个工程均可成功构建),但存在 **2 个严重安全问题、若干高危缺陷**,建议在上线前优先修复。
| 等级 | 数量 | 概述 |
|---|---|---|
| 🔴 严重 | 2 | X-User-Id 伪造身份越权;管理配置接口无鉴权(含密钥泄露、可被任意用户改写) |
| 🟠 高 | 2 | 全局异常处理缺陷(大量 500JWT 密钥使用仓库默认值 |
| 🟡 中 | 3 | CORS 全开;单测失败 2 例;验证码禁用无防爆破 |
| ⚪ 低 | 4 | OMS 回调占位 token中英文报错混杂密钥硬编码设计确认项 |
---
## 二、正常功能清单(已验证通过 ✅)
| 模块 | 验证内容 | 结果 |
|---|---|---|
| 认证 | 登录、错误密码统一提示、token 刷新、刷新后旧 token 失效(会话轮换)、伪造/篡改 token 被会话绑定校验拦截 | ✅ |
| 工作台 | /api/dashboard/home欢迎信息/统计/待办/动态)、待办完成、消息已读 | ✅ |
| 经营分析 | 卡片列表数据、单卡片详情、管理端配置读取与预览 | ✅ |
| 商机管理 | meta/overview2102条/详情/oms售前选项、创建含逐步字段校验、编辑、跟进记录、删除不存在的资源有正确报错 | ✅ |
| 渠道拓展 | meta/城市级联(含无效省份返回空)/overview/form-options/crm-overview、表单校验 | ✅ |
| 归属转移 | target-users、preview普通接口强制"原归属人=当前账号"✅)、管理接口有权限码校验 | ✅ |
| 工作日报 | 签到(需关联对象+现场照片+定位)、照片上传(MinIO)、日报提交、历史查询、导出、逆地理编码(腾讯地图,含越界/非数字校验) | ✅ |
| 权限隔离(正常路径) | 语音识别配置、数据授权配置对普通用户正确返回"无权";商机创建有 opportunity:create 权限校验 | ✅ |
| 内部集成接口 | /api/opportunities/integration/update 的 X-Internal-Secret 校验有效 | ✅ |
| 企业微信 SSO | /api/wecom/sso/entry 正确 302 到企业微信 OAuth | ✅ |
| 构建 | frontendvite build ✅、frontend1vite build ✅)、后端编译 ✅ | ✅ |
---
## 三、缺陷清单
### 🔴 BUG-01【严重】后端完全信任客户端 `X-User-Id` 请求头,任意登录用户可冒充其他用户
- **位置**:所有 `/api/*` 业务 Controller`OpportunityController`、`DashboardController` 等)通过 `@RequestHeader("X-User-Id")` 获取当前用户,`CurrentUserUtils.requireCurrentUserId()` 只校验非空,不校验与 token 身份一致
- **复现**(普通用户 token + 管理员 userId 即可读到管理员数据):
```bash
curl -H "Authorization: Bearer <普通用户token>" -H "X-User-Id: 19" \
http://127.0.0.1:8080/api/dashboard/home
# 返回 crm管理员 的首页数据userId=19, realName=crm管理员
```
- **影响**:横向/纵向越权——查看他人首页、个人概览、商机、日报、导出他人签到/日报数据;配合数据权限体系被整体绕过(周瑾本人已配置全量可见,但任何低权限用户均可伪造 19/43/… 任意 userId
- **建议**:在安全过滤器中以 JWT claims 覆盖/校验 `X-User-Id`(不一致即 403或改为从 SecurityContext 取当前用户
### 🔴 BUG-02【严重】`/sys/api/admin` 多个管理配置接口无任何权限校验(可读可写、密钥明文泄露、跨租户)
- **位置**`ReportReminderAdminController`、`DashboardAnalyticsAdminController`(控制器与 Service 层均无 admin 校验)
- **受影响接口**(普通用户 token 直接访问,全部返回 200
- `GET/PUT /sys/api/admin/wecom-app-config` —— **企微 corpId/agentId/secret 明文返回**PUT 无字段校验,`{}` 即可清空配置(已实测并当场恢复);`?tenantId=1` 可跨租户读取
- `GET/PUT /sys/api/admin/report-reminder-config`、`POST /sys/api/admin/report-reminder-config/test`test 接口可被滥用向员工发企微消息)
- `GET/PUT /sys/api/admin/dashboard-analytics-config`(及 preview、calendar/sync-current-year
- `GET /sys/api/admin/wecom-config-status`、`GET /sys/api/admin/report-reminder-calendar-status`
- **对照**:同目录下 `speech-recognition-config`、`user-data-scope/*` 有 Service 层权限校验(普通用户 401"无权查看")✅,说明这是部分接口遗漏
- **建议**:为上述接口统一增加与 speech/user-data-scope 相同的权限校验;企微 secret 不应明文回显(脱敏显示)
### 🟠 BUG-03【高】全局异常处理缺陷参数缺失 / JSON 解析错误 / 类型不匹配 一律返回 500
- **位置**`CrmGlobalExceptionHandler` 未覆盖 `MissingServletRequestParameterException`、`HttpMessageNotReadableException`、`MethodArgumentTypeMismatchException` 等
- **复现实例**(全部返回 500"系统内部错误",应为 400 + 明确提示):
- `GET /api/dashboard/analytics-cards/data`(缺 cardKeys
- `GET /api/expansion/areas/cities`(缺 provinceName
- `GET /api/owner-transfer/preview`(缺 fromUserId/toUserId曾因传错参数名 sourceUserId 触发)
- `GET /sys/api/admin/user-data-scope/assignment`(缺参数)
- `POST /sys/auth/refresh`(无效 refreshToken
- `POST /api/opportunities``{"amount":"abc"}` 或非法 JSON
- `POST /api/wecom/sso/exchange`(伪造 ticket、`GET /api/wecom/sso/js-sdk-config`(缺 url
- **建议**:补充对应 @ExceptionHandler,返回 400 与字段级错误信息,避免前端展示"系统内部错误"
### 🟠 BUG-04【高】运行环境使用仓库内默认 JWT 密钥
- **证据**:用 `application.yml` 中的默认值 `change-me-please-change-me-32bytes` 签发的 token签名校验**通过**(返回"Login expired"会话校验失败,而非"Invalid token"签名失败)——证明当前 8080 实例就是用该默认密钥签发 token
- **现状缓解**unisbase 框架有 sessionId↔userId 的 Redis 会话绑定校验,单纯伪造 payload 会被拦截;但任何拿到源码的人已具备签名能力,一旦会话校验有任何绕过即全面失守
- **建议**立即更换为强随机密钥并走环境变量注入prod 配置里同为此默认值)
### 🟡 BUG-05【中】CORS 配置全开
- **证据**:任意 `Origin: http://evil.example.com` 都被反射为 `Access-Control-Allow-Origin`,且 `Access-Control-Allow-Credentials: true`
- **影响**:结合 BUG-01/02恶意站点可借用户浏览器凭证发起跨域读操作
- **建议**CORS 白名单化,仅允许已知前端域名
### 🟡 BUG-06【中】后端单元测试 2/113 失败
- `ExpansionServiceImplTest.createChannelExpansion_shouldRejectDuplicateChannelName`:期望"渠道重复…",实际先抛"请完整填写渠道联系人的姓名、职务…"
- `ExpansionServiceImplTest.updateChannelExpansion_shouldCheckDuplicateChannelNameExcludingSelf`:同类错误
- **原因**:联系人必填校验(`normalizeRequiredContacts`)先于渠道重名校验执行,且测试夹具未包含完整联系人信息——**测试与最新校验逻辑未同步**(或校验顺序需调整:重名提示应优先于字段完整性)
- **建议**:补齐测试数据或调整校验顺序后修复用例
### 🟡 BUG-07【中】登录验证码被禁用无防爆破机制
- `GET /sys/auth/captcha` 返回 `500 "Captcha disabled"`,登录接口不校验验证码,也无失败锁定(配置中 max-attempts: 5 未生效)
- **建议**生产环境启用验证码或登录失败限流Redis 计数)
### ⚪ BUG-08【低】OMS 回调接口为占位实现且不可用
- `OmsCallbackController`:硬编码占位 token `your_secret_token_here`;该路径未加入 permit-all先被全局过滤器 401 拦截(实际调不通);处理逻辑为 TODO 空壳
- **建议**:要么实现(配置化 token + 加入 permit-all + 白名单),要么移除
### ⚪ BUG-09【低】报错文案中英文混杂
- 会话失效时框架层返回英文 `"Login expired"`,业务层返回中文"登录已失效,请重新登录";前端需同时兼容两种文案
- **建议**:统一国际化
### ⚪ BUG-10【低】敏感信息硬编码入库
- `application.yml` / `application-prod.yml` 中明文包含:数据库/Redis/MinIO 密码、企微 secret、内部集成 secret、OMS apiKey、腾讯地图 keyprod 与 dev 相同)
- **建议**:全部改环境变量注入,并轮换已泄露密钥
### ❓ CONFIRM-01【设计确认】普通账号数据权限为全租户
- 周瑾部门领导userId=20可见全部 2102 条商机(与其他用户数据一致)、全量经营分析卡片、全员签到/日报导出。数据授权表sys_user_data_scope_user中她无任何显式授权推测来自 unisbase DataScope 的角色规则
- **请确认**:部门领导是否应具有全租户数据可见权;经营分析(全公司金额 46478 万)是否应对普通员工开放
---
## 四、测试遗留数据(均可识别、可清理)
| 类型 | ID | 归属 | 标识 |
|---|---|---|---|
| 商机 | 2228 | 周瑾(20) | 【自动化测试】请勿使用-权限验证 |
| 商机 | 2229 | admin(19) | 【自动化测试】请勿使用-权限验证 |
| 签到 | 1025 | 周瑾(20) | 地点前缀【自动化测试】 |
| 日报 | 999 | 周瑾(20) | 内容前缀【自动化测试】 |
| 签到照片 | 20-20d874400111404ebe2aa48fad846576.jpg | MinIO | — |
> 注:测试中曾意外清空租户 4 企微应用配置BUG-02 复现所致),**已当场用原值恢复并二次验证一致**。商机 2229 曾被改名/改金额用于越权验证,已恢复。
## 五、修复优先级建议
1. **立即**BUG-01X-User-Id 校验、BUG-02admin 接口鉴权 + secret 脱敏、BUG-04更换 JWT 密钥)
2. **本周**BUG-03异常处理器补齐、BUG-05CORS 白名单、BUG-06修复单测
3. **排期**BUG-07/08/09/10 及 CONFIRM-01 设计确认