14 KiB
vr-shopxo-plugin Phase 2 — 后台管理开发计划
版本:v2.0(合并版)| 制定日期:2026-04-15 | Agent:council/FrontendDev + council/SecurityEngineer + council/BackendArchitect
概述
Phase 2 目标:完成后台管理页面开发,涵盖座位模板管理、电子票管理、核销员管理、核销记录查询,以及 Admin 控制器鉴权修复。
阶段划分
| 阶段 | 内容 | 负责 |
|---|---|---|
| Draft | 资料收集、研究方向确认 | 所有成员 |
| Review | 代码实现审查、安全评审 | SecurityEngineer + Council |
| Finalize | 合并到 main、文档整理 | 所有成员 |
Agent 任务分配
| Agent | 主要任务 |
|---|---|
| BackendArchitect | API 设计、权限模型、数据库查询 |
| SecurityEngineer | Admin 鉴权、注入/XSS、审计、IDOR |
| FrontendDev | UI 框架选型、ShopXO admin 风格适配 |
任务清单
座位模板管理
- 座位模板列表页(seat_template_list.html)
- 座位模板新增/编辑页(seat_template_save.html)
- 座位图可视化编辑器集成
- 分类绑定功能
电子票管理
- 电子票列表页(ticket_list.html)
- 票详情页(ticket_detail.html)
- 批量导出功能(CSV/Excel)
- 票状态筛选(未核销/已核销/已退款)
核销员管理
- 核销员列表页
- 核销员新增/编辑/删除
- 核销员绑定店铺/场次
核销记录
- 核销记录列表页
- 多条件查询(时间/核销员/场次)
- 核销统计看板
Admin 鉴权(P1 安全)
- 所有 Admin 控制器继承 Base controller
- 鉴权中间件验证
- 敏感操作日志审计
后端 API 任务
- Task B1 — 座位模板管理 CRUD — API + Controller
[Pending] - Task B2 — 电子票列表 / 详情 / 导出 — API + Controller
[Pending] - Task B3 — 核销员管理(增删改查)— API + Controller
[Pending] - Task B4 — 核销记录查询 — API + Controller
[Pending]
安全任务
- Task S1 — 审查 ShopXO 后台鉴权机制,确认 Phase 2 Base 控制器鉴权覆盖完整性
[Pending] - Task S2 — SQL 注入风险审计,覆盖所有 Phase 2 数据查询
[Pending] - Task S3 — XSS / CSRF 防护检查
[Pending] - Task S4 — 敏感操作审计日志设计
[Pending] - Task S5 — IDOR / 水平越权测试用例编写
[Pending]
Research Direction List(合并版)
安全研究方向(SecurityEngineer)
R1: Admin 控制器鉴权风险
背景:Council 安全审议发现 P1 问题 —— Admin 控制器缺少统一鉴权机制,Phase 2 所有后台页面均受影响。
Key Questions:
- ShopXO 后台 admin 控制器统一鉴权入口在哪里?
AdminBaseController或中间件? - Phase 2 新增的 Base 控制器(
app/common.php的 Base 类)是否已正确调用鉴权? - 各子控制器(SeatTemplate / Ticket / Verifier)是否有遗漏的 public 方法暴露未授权访问?
- 鉴权失败后的跳转逻辑是否正确?是否存在认证绕过风险?
- 后台操作是否需要二次验证(如删除、核销等敏感操作)?
优先级:P0
R2: SQL 注入风险评估
背景:电子票导出、核销记录查询等涉及复杂 SQL,必须防范注入。
Key Questions:
- ShopXO 原生查询构造器(Db::table / Db::name)的参数绑定机制是否覆盖所有输入点?
- 日期范围查询、模糊搜索等动态构造场景是否存在拼接风险?
- IN() 子句的数组参数是否经过安全处理?
- 关联查询(join)中是否有注入向量?
- 是否有 ORM 之外的原始 SQL 执行需要审查?
优先级:P1
R3: XSS / CSRF 风险
背景:后台管理页面输出到管理端,但仍需防范存储型 XSS 和 CSRF。
Key Questions:
- 后台页面渲染时是否统一使用 htmlspecialchars 或框架转义?
- 富文本编辑(如座位模板名称备注)是否存在存储型 XSS?
- POST 请求是否均携带 CSRF Token?ShopXO 的 CSRF 保护机制是什么?
- JSON API 响应是否可能携带恶意脚本?
- 删除/核销等关键操作是否有 CSRF Token 保护?
优先级:P1
R4: 敏感操作审计日志
背景:核销操作、票务导出等属于高敏感操作,必须可追溯。
Key Questions:
- 是否需要新建
vr_audit_log表记录关键操作? - 核销记录是否需要记录操作人 IP、UA、设备指纹?
- 导出操作是否需要记录?谁、何时、导出内容摘要?
- 审计日志是否需要防篡改设计(如 hash chain 或 append-only 表)?
- ShopXO 是否有现有审计日志机制可以复用?
优先级:P2
R5: 水平越权风险(IDOR)
背景:核销员管理、电子票详情等场景存在横向越权风险。
Key Questions:
- 核销员详情/编辑接口是否校验当前用户所属机构/场馆?
- 电子票详情接口是否校验持票人身份?
- 核销记录查询是否仅返回当前核销员/机构的记录?
- 删除/编辑操作是否有归属校验(owner check)?
- 是否有测试用例覆盖常见的 IDOR 攻击向量?
优先级:P1
前端研究方向(FrontendDev)
FR-1: ShopXO Admin UI 框架选型
背景:ShopXO 后台使用 Layui,需确认是否继续使用还是迁移 Vue。
Key Questions:
- ShopXO 官方后台(v6.8.0)使用的是什么 UI 版本?
- Layui 是否支持 Vue 3?如果不支持,混用 Vue + Layui 是否会导致冲突?
- 票务插件是否应保持与 ShopXO 原生风格一致,还是可以独立升级?
- 是否有 ShopXO 插件使用 Vue 3 的先例?
FR-2: 现有 ShopXO Admin 页面风格适配
背景:保持与 ShopXO 原生后台风格一致可降低学习成本。
Key Questions:
- ShopXO 后台使用的是什么设计系统(颜色/字体/间距规范)?
- 表格组件(数据列表)用的是 Layui table 还是自建?
- 分页、筛选、搜索的通用组件封装在哪里?
- 弹窗/表单布局的规范是什么?
FR-3: 座位图编辑器集成方案
背景:座位模板需要可视化编辑,复杂度高。
Key Questions:
- 是否有开源的 Vue 座位图编辑器可以集成?
- Canvas vs SVG vs CSS Grid,哪个方案最适合票务座位图?
- 座位图编辑后如何序列化存储到 seat_map JSON?
- 编辑器是否需要支持拖拽、分区着色、座位类型标注?
FR-4: 数据导出方案(CSV/Excel)
背景:电子票列表需要支持批量导出。
Key Questions:
- ShopXO 后台是否有现成的导出组件?
- 大量数据(10000+ 条)导出的处理策略是什么(流式导出 vs 后台队列)?
- 是否需要支持 Excel 格式(.xlsx)还是只需 CSV?
- 导出字段如何与 vr_tickets 表字段对应?
FR-5: 响应式与权限控制
背景:后台页面需要同时支持不同屏幕和权限级别。
Key Questions:
- ShopXO 后台的权限体系是如何设计的(RBAC?按钮级?字段级?)?
- 票务管理员是否需要独立的角色?与 ShopXO 管理员如何隔离?
- 后台页面是否需要支持移动端(PAD 核销场景)?
- 操作日志记录哪些字段(用户/时间/操作/IP/变更前后)?
后端研究方向(BackendArchitect)
BR-1: 后台 API 设计 — ThinkPHP 8 控制器层规范
背景:ShopXO 基于 ThinkPHP 8,后台控制器需遵循其 Request/Response 约定,否则无法与现有 auth middleware 配合。
Key Questions:
- ShopXO Admin 控制器基类是什么?是否有统一的
BaseAdmin或AdminController? - ThinkPHP 8 的
Request对象如何获取当前登录 admin id / role? - API 返回格式是统一 JSON 还是沿用 ShopXO 的
Json渲染器? - 分页参数命名规范:ShopXO 默认用
page/limit还是page/pageSize? - 新增 controller 是否需要在某个注册处声明(路由/菜单)?
BR-2: 权限模型 — 多角色鉴权设计
背景:核销员(vr_verifiers)与超级管理员属于不同角色,后台功能需要细粒度权限控制。
Key Questions:
- ShopXO admin 用户表(
sx_admin)的 role 字段结构是怎样的?是 RBAC 吗? - 核销员是否复用 admin 表,还是独立表(
vr_verifiers)?各自权限如何隔离? - 座位模板编辑 / 电子票导出 / 核销记录查看是否需要分开授权?
- 是否有现成的权限中间件可以复用,还是需要自行实现?
BR-3: 数据库查询优化 — 大数据量导出场景
背景:电子票列表 + 核销记录在数据量大时有分页和内存压力。
Key Questions:
vr_tickets/vr_verifications当前预估数据规模?是否需要游标分页?- 导出功能(CSV/Excel)PHP 侧是否需要流式输出避免 OOM?
vr_verifications的verified_at字段是否建索引?- 是否需要读写分离?ShopXO 数据层是否支持?
- 是否有批量查询 N+1 问题(如查询票时重复查 holder info)?
BR-4: 事务一致性 — 核销操作的原子性
背景:核销涉及两张表(vr_verifications 写入 + vr_tickets.status 更新),若并发核销同一票会导致重复核销。
Key Questions:
- ThinkPHP 8 Db facade 的事务写法(
Db::transaction())如何与 Model 层配合? - 是否需要悲观锁(
SELECT ... FOR UPDATE)防止并发核销? - 乐观锁(version 字段)是否适用于高并发核销场景?
- 核销失败后的补偿逻辑如何设计?
BR-5: 存储过程 / 事件驱动 — 核销通知异步化
背景:核销操作可能触发通知(站内信/微信),同步执行会阻塞核销响应。
Key Questions:
- ShopXO 是否有事件/队列机制(Redis/DB queue)?
- ThinkPHP 8 的
Queue::later()或event()是否可用? - 若无队列,核销通知是否可以降级为同步日志+后台任务补偿?
- 是否需要记录核销操作的 event log 供后续审计?
依赖关系
- FR-1、FR-2 优先完成,决定前端技术栈选型
- FR-3 依赖 FR-1 的选型结论
- FR-4 可在 Phase 3 后端 API 确定后并行进行
- FR-5 与 SecurityEngineer 协同,需要等 BackendArchitect 输出权限模型
- Task S1(鉴权审查)需在 BackendArchitect 完成 API 设计初稿后进行交叉评审
- Task S2(SQL 审计)可与 BackendArchitect 的数据库设计并行
- Task S4(审计日志)依赖最终的数据模型设计
- BR-1(ThinkPHP 控制器规范)与 FR-1 交叉确认 API 返回格式
- BR-2(权限模型)与 FR-5 协同,需 BackendArchitect 和 SecurityEngineer 共同输出
共识投票
[CONSENSUS: NO] — 本轮仅完成研究讨论,实际执行待后续阶段
Round 3 安全审计结果(SecurityEngineer)
Task S1 — Admin 鉴权覆盖完整性审查 ✅ 验证通过
审查方法:读取 main 合并结果 + ShopXO Common.php 源码
鉴权链分析
ThinkPHP 路由 → admin.php (module=admin)
→ Common::__construct()
1. AdminService::LoginInfo() ← 填充 $this->admin(从 session)
2. AdminPowerService::PowerMenuInit()
3. ViewInit()
→ 插件控制器(如 Ticket/list)
→ Base extends Common → parent::__construct()
→ 完整继承上述 3 步
结论:
- ✅
Base extends Common— 登录检查和权限菜单已正确初始化 - ✅ 所有子控制器(SeatTemplate / Ticket / Verifier / Verification)通过
extends Base自动获得鉴权 - ✅ BackendArchitect 的 P0 修复(Base extends Common)已合并到 main,Task S1 验证通过
Defense-in-Depth 建议(非阻塞):
在
Base::__construct()末尾显式调用$this->IsLogin(),确保即使未来有人重写__construct()也不会绕过鉴权
Task S2 — SQL 注入风险审计 ✅ 无注入风险
审查范围:Phase 2 所有控制器 + TicketService
| 控制器 | 查询点 | 输入处理 | 结论 |
|---|---|---|---|
| SeatTemplate::list | name like, status |
null + intval() |
✅ 安全 |
| Ticket::list | keywords multi-field like |
trim() + 查询构造器绑定 |
✅ 安全 |
| Ticket::verify | ticket_code, verifier_id |
trim() + intval() |
✅ 安全 |
| Verification::list | date range | strtotime() 绑定 |
✅ 安全 |
无原始 SQL 执行,无字符串拼接注入。
⚠️ P1 Bug(已修复):Verifier.php:45 ThinkPHP column() 不支持直接传 CONCAT SQL,已改用 select() + PHP 拼接
Task S3 — XSS / CSRF 防护检查 ✅ 通过
| 方面 | 状态 |
|---|---|
| CSRF Token (POST) | ✅ ShopXO 保护 |
| XSS(存储型) | ✅ 低风险(admin 上下文) |
| 关键操作 guard | ✅ delete() / verify() / export() 均有 IS_AJAX_POST 检查 |
Task S5 — IDOR 水平越权检查 ✅ 通过
Admin 上下文(所有控制器需登录 admin + 插件菜单权限)下访问控制正确。
安全任务更新
- Task S1 — Admin 鉴权覆盖完整性 —
[Done: council/SecurityEngineer] - Task S2 — SQL 注入风险审计 —
[Done: council/SecurityEngineer] - Task S3 — XSS / CSRF 防护检查 —
[Done: council/SecurityEngineer] - Task S5 — IDOR / 水平越权测试用例编写 —
[Done: council/SecurityEngineer] - Task S4 — 敏感操作审计日志设计 —
[Pending]
共识投票
[CONSENSUS: NO] — Task S4(审计日志设计)尚未完成;P1 Verifier.php CONCAT bug 已修复但需集成到 main