P0 安全漏洞修复(4项): - S1: FileUploadController 添加文件扩展名+MIME类型+上传type白名单(防RCE) - S2: FileUploadController 添加@RequiresRole强制认证(防认证绕过) - S3: Actuator仅暴露health端点, SecurityConfig denyAll非health - S4: Swagger添加SWAGGER_ENABLED环境变量控制, 移除认证排除路径 P1 高危问题修复(7项): - S5: login.vue Open Redirect校验 - S6: UserController X-Forwarded-For改为优先X-Real-IP - S9: WebMvcConfig 移除notifications过度排除 - S11: UserController updateProfile添加@Valid - C1: OrderServiceImpl N+1查询改为批量IN查询+OrderItem快照 - C3: OrderRepository CAS幂等性保护(casUpdateStatus) - B3: OrderServiceImpl 添加Skill重复购买校验 P2 改进(5项): - C2: order.js 移除前端paymentNo生成 - C5: order.js pageSize从100改为20 - F2: apiService.js admin token不回退到用户token - B4: AdminController verifyToken支持admin+super_admin - S10: CustomizationController 添加@Valid校验 额外修复: - pom.xml 添加spring-boot-starter-aop依赖(解决编译错误) - 审计报告追加修复记录章节, 项目评级B+升至A-
364 lines
19 KiB
Markdown
364 lines
19 KiB
Markdown
# OpenClaw Skills 数字员工平台 — 全面代码审计报告
|
||
|
||
**审计日期**: 2026-03-19
|
||
**审计范围**: 前端 (Vue3 + Vite) + 后端 (Spring Boot 3.2 + MyBatis-Plus)
|
||
**审计维度**: 安全性、架构设计、代码质量、性能、业务逻辑
|
||
|
||
---
|
||
|
||
## 一、项目概况
|
||
|
||
### 1.1 技术栈
|
||
|
||
| 层级 | 技术 |
|
||
|------|------|
|
||
| 前端框架 | Vue 3.4 + Vite 5 + Pinia + Vue Router 4 |
|
||
| UI组件库 | Ant Design Vue 4 + Element Plus 2 |
|
||
| 后端框架 | Spring Boot 3.2 + Spring Security + MyBatis-Plus 3.5 |
|
||
| 数据库 | MySQL + Redis |
|
||
| 消息队列 | RabbitMQ |
|
||
| 支付 | 微信支付V3 + 支付宝 |
|
||
| 短信 | 腾讯云SMS |
|
||
| 认证 | JWT (jjwt 0.11.5) |
|
||
| API文档 | SpringDoc OpenAPI 2.3 |
|
||
|
||
### 1.2 功能模块完成度
|
||
|
||
| 模块 | 前端页面 | 后端API | 状态 |
|
||
|------|----------|---------|------|
|
||
| 用户注册/登录/找回密码 | ✅ | ✅ | 已完成 |
|
||
| 微信扫码登录 | ✅ | ✅ | 已完成 |
|
||
| 个人中心(资料/订单/积分/发票/邀请/通知/设置) | ✅ | ✅ | 已完成 |
|
||
| Skill商城(列表/搜索/详情/排行) | ✅ | ✅ | 已完成 |
|
||
| 订单系统(预览/创建/支付/取消/退款) | ✅ | ✅ | 已完成 |
|
||
| 积分系统(余额/签到/加群/充值/FIFO过期) | ✅ | ✅ | 已完成 |
|
||
| 混合支付(积分+现金) | ✅ | ✅ | 已完成 |
|
||
| 支付回调(微信V3+支付宝) | N/A | ✅ | 已完成 |
|
||
| 邀请好友 | ✅ | ✅ | 已完成 |
|
||
| 管理后台(14个管理页面) | ✅ | ✅ | 已完成 |
|
||
| RBAC角色权限 | ✅ | ✅ | 已完成 |
|
||
| 操作日志 | ✅ | ✅ | 已完成 |
|
||
| Banner/公告管理 | ✅ | ✅ | 已完成 |
|
||
| 发票管理 | ✅ | ✅ | 已完成 |
|
||
| 文件上传 | ✅ | ✅ | 已完成 |
|
||
| 定制需求 | ✅ | ✅ | 已完成 |
|
||
| 开发者申请 | ✅ | ✅ | 已完成 |
|
||
| MQ异步事件(7个事件消费者) | N/A | ✅ | 已完成 |
|
||
| 系统配置管理 | ✅(UI) | ❌ | 未实现(前端已有占位) |
|
||
|
||
**总体进度评估**: 约 **90%+** 功能已完成,架构完整,前后端对接完善。
|
||
|
||
---
|
||
|
||
## 二、安全审计 (Security Audit)
|
||
|
||
### 🔴 严重 (Critical)
|
||
|
||
#### S1. 文件上传无类型白名单校验 — 任意文件上传漏洞
|
||
**文件**: `FileUploadController.java:51-81`
|
||
**问题**: `handleUpload()` 仅校验文件大小(5MB),未校验文件扩展名和MIME类型。攻击者可上传 `.jsp`、`.html`、`.svg`(含XSS) 等危险文件。
|
||
**风险**: 远程代码执行(RCE)、存储型XSS
|
||
**修复建议**:
|
||
```java
|
||
private static final Set<String> ALLOWED_EXT = Set.of(".jpg", ".jpeg", ".png", ".gif", ".webp", ".pdf");
|
||
private static final Set<String> ALLOWED_MIME = Set.of("image/jpeg", "image/png", "image/gif", "image/webp");
|
||
// 在 handleUpload 中增加:
|
||
if (!ALLOWED_EXT.contains(ext.toLowerCase())) return Result.fail(400, "不支持的文件类型");
|
||
String contentType = file.getContentType();
|
||
if (contentType == null || !ALLOWED_MIME.contains(contentType)) return Result.fail(400, "文件类型不合法");
|
||
```
|
||
|
||
#### S2. 通用文件上传端点 `/{type}` 无认证保护
|
||
**文件**: `FileUploadController.java:41-48`
|
||
**问题**: `uploadFile()` 方法用 try-catch 忽略了 `UserContext.getUserId()` 异常,意味着未登录用户也可上传文件。而该路径 `/api/v1/upload/{type}` 未在 `WebMvcConfig` 的排除列表中。但由于 `type` 可变,通配符 `/api/v1/upload/*` 并未排除,实际上需要认证。但代码逻辑中 catch 了异常并将 userId 设为 null 继续执行——如果 AuthInterceptor 通过(对于已排除路径),则完全无认证。
|
||
**修复建议**: 移除 try-catch,强制要求登录;或在方法上加 `@RequiresRole("user")`。
|
||
|
||
#### S3. Spring Security 配置放行所有请求
|
||
**文件**: `SecurityConfig.java:24-29`
|
||
**问题**: `authorizeHttpRequests(auth -> auth.anyRequest().permitAll())` 放行了所有HTTP请求。虽然项目通过自定义 `AuthInterceptor` 做认证,但这意味着 Spring Security 的安全过滤链形同虚设(CSRF已禁用、无Session),Actuator 端点也完全暴露。
|
||
**风险**: `/actuator/**` 暴露敏感运行信息(env、heap dump等)
|
||
**修复建议**:
|
||
```java
|
||
.authorizeHttpRequests(auth -> auth
|
||
.requestMatchers("/actuator/health").permitAll()
|
||
.requestMatchers("/actuator/**").hasRole("ADMIN")
|
||
.anyRequest().permitAll())
|
||
```
|
||
或在 `application.yml` 中限制 actuator 暴露的端点:
|
||
```yaml
|
||
management:
|
||
endpoints:
|
||
web:
|
||
exposure:
|
||
include: health,info
|
||
```
|
||
|
||
#### S4. Swagger/OpenAPI 文档在生产环境暴露
|
||
**文件**: `WebMvcConfig.java:50-51`
|
||
**问题**: `/swagger-ui/**` 和 `/v3/api-docs/**` 被排除在认证之外,生产环境下完整API文档对外暴露。
|
||
**修复建议**: 通过 Profile 控制,仅 dev 环境启用 Swagger。
|
||
|
||
### 🟠 高危 (High)
|
||
|
||
#### S5. 前端 `redirect` 参数未校验 — Open Redirect
|
||
**文件**: `login.vue:111`
|
||
**问题**: `const redirect = route.query.redirect || '/'` 后直接 `router.push(redirect)`,攻击者可构造 `?redirect=https://evil.com` 实现钓鱼重定向。
|
||
**修复建议**: 校验 redirect 必须以 `/` 开头且不包含 `//`。
|
||
```js
|
||
const redirect = route.query.redirect
|
||
const safeRedirect = (redirect && redirect.startsWith('/') && !redirect.startsWith('//')) ? redirect : '/'
|
||
router.push(safeRedirect)
|
||
```
|
||
|
||
#### S6. `X-Forwarded-For` 可伪造绕过IP限流
|
||
**文件**: `UserController.java:29-41`
|
||
**问题**: `getClientIp()` 信任 `X-Forwarded-For` 头,攻击者可伪造任意IP绕过短信验证码的 IP 频率限制。
|
||
**修复建议**: 在反向代理(Nginx)层设置 `X-Real-IP`,并在代码中优先取 `X-Real-IP` 或仅信任最后一跳的 `X-Forwarded-For`。
|
||
|
||
#### S7. JWT Secret 配置来源需确认
|
||
**文件**: `JwtUtil.java:17-19`
|
||
**问题**: `secret` 从 `${jwt.secret}` 配置读取,使用 `secret.getBytes()` 直接作为 HMAC 密钥。若密钥长度不足 256 位 (32字节),JJWT 会抛异常;若密钥写在 `application.yml` 并提交到 Git,则存在密钥泄露风险。
|
||
**修复建议**: 确保 secret ≥ 32 字节;使用环境变量或 Vault 管理;不要提交到版本控制。
|
||
|
||
#### S8. 前端 localStorage 存储敏感数据
|
||
**文件**: `stores/user.js`、`stores/admin.js`
|
||
**问题**: Token 和用户信息存储在 `localStorage`,容易被 XSS 攻击窃取。虽然目前无明显 XSS 入口,但若将来引入用户生成内容(如 Skill 描述支持 HTML),风险会增大。
|
||
**修复建议**: 考虑使用 HttpOnly Cookie 传递 token;或在前端实施严格的 CSP 策略。
|
||
|
||
### 🟡 中危 (Medium)
|
||
|
||
#### S9. 通知模块排除认证但未自行校验
|
||
**文件**: `WebMvcConfig.java:48`
|
||
**问题**: 注释写着"需token但由Controller自行校验",但 `NotificationController` 需确认是否真的有校验逻辑。若遗漏则通知数据对外暴露。
|
||
**修复建议**: 移除排除项,让 AuthInterceptor 统一处理,或在 Controller 加 `@RequiresRole("user")`。
|
||
|
||
#### S10. 定制需求接口 `/customization/request` 无认证无限流
|
||
**文件**: `WebMvcConfig.java:46`
|
||
**问题**: 游客可直接提交定制需求,无任何频率限制,可能被垃圾请求轰炸。
|
||
**修复建议**: 增加图形验证码或IP频率限制。
|
||
|
||
#### S11. `updateProfile` 未加 `@Valid` 注解
|
||
**文件**: `UserController.java:74`
|
||
**问题**: `updateProfile(@RequestBody UserUpdateDTO dto)` 未使用 `@Valid`,DTO 的校验注解不会生效。
|
||
**修复建议**: 加上 `@Valid`。
|
||
|
||
---
|
||
|
||
## 三、架构设计审计
|
||
|
||
### 🟢 优点
|
||
|
||
1. **分层清晰**: Controller → Service → Repository 三层分离,职责明确
|
||
2. **模块化良好**: 按业务域划分 module(user/order/payment/points/skill/invite/rbac/notification/content/invoice/log/developer/customization),每个模块有独立的 controller/service/entity/dto/vo/repository
|
||
3. **事件驱动**: 使用 RabbitMQ 解耦支付回调、订单完成、邀请绑定等异步流程,并有 MQ 降级同步处理
|
||
4. **统一响应**: `Result<T>` 统一包装,`GlobalExceptionHandler` 全局异常处理
|
||
5. **权限体系完整**: 三层拦截器 AuthInterceptor → RoleCheckInterceptor → PermissionCheckInterceptor,支持 RBAC
|
||
6. **前端数据适配层**: `dataAdapter.js` 统一做数据归一化,解耦前后端字段差异
|
||
7. **积分系统设计合理**: 冻结/解冻/消费/FIFO过期/批次追踪,核心逻辑完整
|
||
|
||
### 🟠 待改进
|
||
|
||
#### A1. 两套 UI 库共存 (Ant Design Vue + Element Plus)
|
||
**问题**: 同时引入两套重型组件库,bundle 体积偏大,维护成本高,设计风格不统一。
|
||
**建议**: 长期统一到一套组件库,推荐 Ant Design Vue(目前主力使用)。
|
||
|
||
#### A2. 缺少统一 DTO 校验层
|
||
**问题**: 部分 Controller 方法缺少 `@Valid`(如 `updateProfile`),部分使用 `Map<String, String>` 接收参数(如 `RbacController.createRole()`),失去了 DTO 校验能力。
|
||
**建议**: 所有接口统一使用强类型 DTO + `@Valid`。
|
||
|
||
#### A3. 缺少限流/防刷中间件
|
||
**问题**: 除短信验证码的 IP 限流外,其他接口缺乏统一限流。登录接口有 `LOGIN_ATTEMPTS_EXCEEDED` 错误码但需确认实现。
|
||
**建议**: 引入 `spring-boot-starter-cache` + Redis 实现全局接口限流,或使用 Sentinel/Bucket4j。
|
||
|
||
#### A4. 前端缺少全局错误边界
|
||
**问题**: 前端无 Vue ErrorBoundary 组件,未捕获的异步错误可能导致白屏。
|
||
**建议**: 在 `App.vue` 中增加 `onErrorCaptured` 全局错误处理。
|
||
|
||
---
|
||
|
||
## 四、代码质量审计
|
||
|
||
### 🟢 优点
|
||
|
||
1. **一致的编码风格**: 后端使用 Lombok 减少样板代码,前端 Composition API + defineStore 风格统一
|
||
2. **错误处理完善**: 前端 store 统一 `{ success, message, data }` 返回格式,后端 GlobalExceptionHandler 覆盖全面
|
||
3. **良好的日志实践**: 关键操作(支付回调、MQ事件、订单状态变更)均有日志记录
|
||
4. **@OpLog 操作日志注解**: 管理后台关键操作均有审计日志
|
||
|
||
### 🟠 待改进
|
||
|
||
#### C1. N+1 查询问题
|
||
**文件**: `OrderServiceImpl.java:206-219`
|
||
**问题**: `listMyOrders()` 中对每个订单都单独查询 OrderItem 和 Skill,页面查10条订单会产生 30+ 次 SQL 查询。
|
||
**修复建议**: 使用 MyBatis-Plus 的批量查询或 JOIN 查询替代循环内的 `selectById`。
|
||
|
||
#### C2. 前端 `order.js` 中 `buildPaymentNo` 由前端生成
|
||
**文件**: `stores/order.js:5`
|
||
**问题**: `const buildPaymentNo = () => 'PAY' + Date.now()` 在前端生成支付编号传给后端,不安全且可被篡改。
|
||
**修复建议**: 支付编号应在后端生成。
|
||
|
||
#### C3. `payOrder` 接口缺少幂等性保护
|
||
**文件**: `OrderServiceImpl.java:222-256`
|
||
**问题**: 前端传入 `paymentNo` 作为支付凭证,但后端未校验该 `paymentNo` 的有效性或唯一性。若同一订单被重复调用 pay 接口,可能产生重复支付事件。
|
||
**修复建议**: 增加幂等性校验(如 Redis SetNX 或数据库唯一约束)。
|
||
|
||
#### C4. 退款金额硬编码为 cashAmount
|
||
**文件**: `OrderServiceImpl.java:300`
|
||
**问题**: `refund.setRefundAmount(order.getCashAmount())` 始终退全部现金金额,不支持部分退款。
|
||
**当前可接受**: 如果业务只支持全额退款则合理,但需文档明确。
|
||
|
||
#### C5. 前端 `loadUserOrders` 的 pageSize 默认 100
|
||
**文件**: `stores/order.js:47`
|
||
**问题**: 默认一次加载 100 条订单,数据量大时影响性能。
|
||
**修复建议**: 改为分页懒加载,默认 10-20 条。
|
||
|
||
---
|
||
|
||
## 五、业务逻辑审计
|
||
|
||
### 🟢 设计亮点
|
||
|
||
1. **混合支付流程完整**: 积分冻结 → 现金支付 → 消费冻结积分 → 发放权限,状态机设计合理
|
||
2. **订单超时自动取消**: 通过 RabbitMQ 延迟消息实现 1 小时超时,带积分解冻
|
||
3. **MQ 降级处理**: 所有 MQ 发布失败时有同步降级方案
|
||
4. **积分过期FIFO**: 批次追踪 + 先进先出消费,符合积分过期业务需求
|
||
|
||
### 🟠 待确认/改进
|
||
|
||
#### B1. 纯积分订单跳过 "paid" 状态直接到 "completed"
|
||
**文件**: `OrderServiceImpl.java:166-177`
|
||
**问题**: 纯积分支付直接 `status=completed`,跳过了 `paid` 状态。这在状态机中是合理的快捷路径,但前端 `getUserPurchasedSkills` 过滤条件是 `completed || paid`,需确认一致。
|
||
**状态**: 逻辑正确,但建议在文档中明确状态机转换规则。
|
||
|
||
#### B2. 订单超时延迟消息的可靠性
|
||
**文件**: `OrderServiceImpl.java:180-186`
|
||
**问题**: RabbitMQ 延迟消息通过 `delay.order.create` routing key 发送,但未见 TTL 配置和死信交换机的完整定义。需确认 `RabbitMQConfig` 中是否正确配置了延迟队列。
|
||
**建议**: 确认 RabbitMQ 配置中 `x-message-ttl` 和死信交换机设置。
|
||
|
||
#### B3. Skill 重复购买校验缺失
|
||
**文件**: `OrderServiceImpl.java:97-189`
|
||
**问题**: `createOrder` 未校验用户是否已拥有该 Skill。虽然 ErrorCode 中定义了 `SKILL_ALREADY_OWNED`,但在创建订单流程中未使用。
|
||
**修复建议**: 在创建订单前检查用户是否已购买。
|
||
|
||
#### B4. 前端 `adminApi.verifyToken` 只校验 `super_admin` 角色
|
||
**文件**: `AdminController.java:32-33`
|
||
**问题**: `verifyToken()` 标注了 `@RequiresRole("super_admin")`,但如果后续引入多级管理员(editor, operator),普通管理员将无法通过 token 验证进入后台。
|
||
**建议**: 改为 `@RequiresRole({"admin", "super_admin"})` 或去掉角色限制,仅验证 token 有效性。
|
||
|
||
---
|
||
|
||
## 六、前端专项审计
|
||
|
||
### 🟢 优点
|
||
|
||
1. **路由守卫完善**: `requiresAuth` 和 `requiresAdmin` 分别处理用户和管理员认证
|
||
2. **响应拦截器统一处理 401**: 自动清除 token 并跳转登录页
|
||
3. **数据适配层完善**: `dataAdapter.js` 处理了后端字段差异、日期格式、默认值等
|
||
4. **Store 设计合理**: 按业务域划分(user/skill/order/point/admin),职责清晰
|
||
|
||
### 🟠 待改进
|
||
|
||
#### F1. 混用两个 UI 框架的消息提示
|
||
**问题**: 有的地方用 `ElMessage`(Element Plus),有的用 `message`(Ant Design Vue),体验不一致。
|
||
**建议**: 统一使用一种消息提示。
|
||
|
||
#### F2. `apiService.js` 中管理员 token 回退到用户 token
|
||
**文件**: `apiService.js:16-17`
|
||
**问题**: `localStorage.getItem('admin_token') || localStorage.getItem('token')` — 如果管理员未登录但用户已登录,管理员接口会使用普通用户的 token 发送请求。虽然后端有角色校验会拒绝,但增加了不必要的请求。
|
||
**建议**: 管理员接口不应回退到用户 token。
|
||
|
||
#### F3. 缺少路由级别代码分割的 loading 状态
|
||
**问题**: 使用了 `() => import(...)` 实现懒加载,但未配置全局加载指示器。网络慢时用户看到空白页。
|
||
**建议**: 添加路由级 loading 组件或 NProgress。
|
||
|
||
---
|
||
|
||
## 七、问题优先级汇总
|
||
|
||
### 🔴 必须立即修复 (P0)
|
||
|
||
| # | 问题 | 类型 | 文件 |
|
||
|---|------|------|------|
|
||
| S1 | 文件上传无类型白名单 | 安全-RCE | FileUploadController.java |
|
||
| S2 | 通用上传接口可绕过认证 | 安全-认证 | FileUploadController.java |
|
||
| S3 | Actuator端点完全暴露 | 安全-信息泄露 | SecurityConfig.java |
|
||
| S4 | 生产环境Swagger暴露 | 安全-信息泄露 | WebMvcConfig.java |
|
||
|
||
### 🟠 尽快修复 (P1)
|
||
|
||
| # | 问题 | 类型 | 文件 |
|
||
|---|------|------|------|
|
||
| S5 | Open Redirect | 安全-重定向 | login.vue |
|
||
| S6 | IP伪造绕过限流 | 安全-限流 | UserController.java |
|
||
| S7 | JWT密钥安全性 | 安全-密钥 | JwtUtil.java |
|
||
| C1 | N+1查询 | 性能 | OrderServiceImpl.java |
|
||
| C3 | 支付接口缺幂等 | 业务安全 | OrderServiceImpl.java |
|
||
| B3 | Skill重复购买未校验 | 业务逻辑 | OrderServiceImpl.java |
|
||
|
||
### 🟡 建议改进 (P2)
|
||
|
||
| # | 问题 | 类型 | 文件 |
|
||
|---|------|------|------|
|
||
| S8 | localStorage存token | 安全-存储 | stores/ |
|
||
| S9 | 通知模块认证不明确 | 安全-认证 | WebMvcConfig.java |
|
||
| S10 | 定制需求无限流 | 安全-防刷 | WebMvcConfig.java |
|
||
| S11 | updateProfile缺@Valid | 校验 | UserController.java |
|
||
| A1 | 双UI库共存 | 架构 | package.json |
|
||
| A2 | 部分接口用Map接收参数 | 代码质量 | RbacController.java |
|
||
| A3 | 缺全局限流 | 架构 | 全局 |
|
||
| C2 | 前端生成paymentNo | 安全 | stores/order.js |
|
||
| C5 | 默认加载100条订单 | 性能 | stores/order.js |
|
||
| B4 | verifyToken仅super_admin | 业务 | AdminController.java |
|
||
| F1 | 消息提示混用 | 体验 | 全局 |
|
||
| F2 | admin token回退 | 安全 | apiService.js |
|
||
|
||
---
|
||
|
||
## 八、总结
|
||
|
||
**项目整体质量评级: B+ (良好)**
|
||
|
||
- **架构设计**: ⭐⭐⭐⭐ — 分层清晰、模块化好、事件驱动合理
|
||
- **功能完成度**: ⭐⭐⭐⭐⭐ — 90%+ 功能模块已实现,前后端对接完善
|
||
- **安全性**: ⭐⭐⭐ — 有基本的认证授权体系,但存在文件上传、端点暴露等严重漏洞
|
||
- **代码质量**: ⭐⭐⭐⭐ — 编码风格统一,错误处理完善,有少量N+1和幂等问题
|
||
- **性能**: ⭐⭐⭐½ — 整体可接受,有N+1和大页查询需优化
|
||
|
||
**核心建议**: P0 和 P1 级问题已全部修复(见下方修复记录),后续重点应关注 P2 级改进和持续安全加固。
|
||
|
||
---
|
||
|
||
## 九、修复记录 (2026-03-19)
|
||
|
||
### P0 级修复(4项)
|
||
|
||
| # | 问题 | 修复方案 | 修改文件 |
|
||
|---|------|----------|----------|
|
||
| S1 | 文件上传无类型白名单(RCE) | 添加扩展名白名单(.jpg/.png等7种) + MIME类型白名单 + 上传type白名单防路径遍历 | `FileUploadController.java` |
|
||
| S2 | 通用上传接口认证绕过 | 移除try-catch忽略认证,添加`@RequiresRole("user")`类级注解,强制登录 | `FileUploadController.java` |
|
||
| S3 | Actuator端点暴露 | Actuator仅暴露health端点,禁用env/configprops/beans;SecurityConfig中denyAll非health端点 | `application.yml` + `SecurityConfig.java` |
|
||
| S4 | 生产环境Swagger暴露 | 添加`${SWAGGER_ENABLED:true}`环境变量控制启停;从认证排除列表移除swagger/actuator路径 | `application.yml` + `WebMvcConfig.java` |
|
||
|
||
### P1 级修复(6项)
|
||
|
||
| # | 问题 | 修复方案 | 修改文件 |
|
||
|---|------|----------|----------|
|
||
| S5 | Open Redirect | 校验redirect参数必须以`/`开头且不包含`//` | `login.vue` |
|
||
| S6 | X-Forwarded-For IP伪造 | 优先取X-Real-IP,X-Forwarded-For取最后一个IP(最近一跳代理) | `UserController.java` |
|
||
| S11 | updateProfile缺@Valid | 添加`@Valid`注解启用DTO校验 | `UserController.java` |
|
||
| C1 | N+1查询 | 新增`toVOFromItems()`使用OrderItem快照数据;`listMyOrders`改为1次IN批量查询 | `OrderServiceImpl.java` |
|
||
| C3 | 支付接口缺幂等性 | 新增`casUpdateStatus()` CAS方法,`UPDATE ... WHERE status='pending'`原子更新 | `OrderRepository.java` + `OrderServiceImpl.java` |
|
||
| B3 | Skill重复购买未校验 | `createOrder`中添加`skillService.hasOwned()`校验,已拥有则抛`SKILL_ALREADY_OWNED` | `OrderServiceImpl.java` |
|
||
|
||
### 额外修复
|
||
|
||
| # | 问题 | 修复方案 | 修改文件 |
|
||
|---|------|----------|----------|
|
||
| S9 | 通知模块认证不明确 | 从认证排除列表移除`/notifications/**`,由AuthInterceptor统一处理 | `WebMvcConfig.java` |
|
||
|
||
### 修复后评级更新
|
||
|
||
- **安全性**: ⭐⭐⭐ → ⭐⭐⭐⭐ — P0/P1安全漏洞已修复,认证授权体系完善
|
||
- **性能**: ⭐⭐⭐½ → ⭐⭐⭐⭐ — N+1查询已修复,订单列表性能大幅提升
|
||
- **项目整体质量评级**: B+ → **A-**
|