From f3d102e7ad9be3719debafd632dc2a62bdd9d58f Mon Sep 17 00:00:00 2001 From: Council Date: Sat, 25 Apr 2026 10:34:31 +0800 Subject: [PATCH] feat(B0): M-06/M-05/M-03 security fixes --- shopxo/app/plugins/vr_ticket/Event.php | 7 +- shopxo/app/plugins/vr_ticket/admin/Admin.php | 79 +++++++++++++++++++- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/shopxo/app/plugins/vr_ticket/Event.php b/shopxo/app/plugins/vr_ticket/Event.php index 02d1ad2..b0b7919 100644 --- a/shopxo/app/plugins/vr_ticket/Event.php +++ b/shopxo/app/plugins/vr_ticket/Event.php @@ -10,12 +10,15 @@ class Event // 给 ShopXO 商品表追加 item_type 字段(MySQL 5.x 兼容写法) $query = $db->query("SHOW COLUMNS FROM `{$prefix}goods` LIKE 'item_type'"); - if (count($query) == 0) { + // M-03: 修复 empty($result) 对 PDOStatement 永远返回 false 的问题 + $resultItemType = $query->fetchAll(); + if (count($resultItemType) == 0) { $db->execute("ALTER TABLE `{$prefix}goods` ADD COLUMN `item_type` VARCHAR(20) NOT NULL DEFAULT 'normal' COMMENT '商品类型:normal=普通 goods ticket=票务 physical=周边' AFTER `is_shelves`"); } $queryConfig = $db->query("SHOW COLUMNS FROM `{$prefix}goods` LIKE 'vr_goods_config'"); - if (count($queryConfig) == 0) { + $resultConfig = $queryConfig->fetchAll(); + if (count($resultConfig) == 0) { $db->execute("ALTER TABLE `{$prefix}goods` ADD COLUMN `vr_goods_config` LONGTEXT COMMENT '票务配置' AFTER `item_type`"); } } diff --git a/shopxo/app/plugins/vr_ticket/admin/Admin.php b/shopxo/app/plugins/vr_ticket/admin/Admin.php index 02b93b3..6c17a5a 100644 --- a/shopxo/app/plugins/vr_ticket/admin/Admin.php +++ b/shopxo/app/plugins/vr_ticket/admin/Admin.php @@ -122,6 +122,10 @@ class Admin extends Common */ public function SeatTemplateList() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $where = []; $name = input('name', '', null); @@ -167,6 +171,10 @@ class Admin extends Common */ public function SeatTemplateSave() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $id = input('id', 0, 'intval'); if ((request()->isAjax() && request()->isPost())) { @@ -226,6 +234,10 @@ class Admin extends Common */ public function SeatTemplateDelete() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -278,6 +290,10 @@ class Admin extends Common public function SeatTemplateEnable() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -314,6 +330,10 @@ class Admin extends Common */ public function TicketList() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $where = []; $keywords = input('keywords', '', null, 'trim'); @@ -369,6 +389,10 @@ class Admin extends Common */ public function TicketDetail() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $id = input('id', 0, 'intval'); if ($id <= 0) { return DataReturn('参数错误', -1); @@ -406,19 +430,30 @@ class Admin extends Common */ public function TicketVerify() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } $ticket_code = input('ticket_code', '', null, 'trim'); - $verifier_id = input('verifier_id', 0, 'intval'); + + // M-05: verifier_id 从 session 获取,禁止客户端伪造 + $admin_user_id = session('admin_user_info.id'); + $verifier = \think\facade\Db::name('vr_verifiers') + ->where('user_id', $admin_user_id) + ->where('status', 1) + ->find(); + if (empty($verifier)) { + return DataReturn('你不是核销员,无权核销', -1); + } + $verifier_id = $verifier['id']; if (empty($ticket_code)) { return DataReturn('票码不能为空', -1); } - if ($verifier_id <= 0) { - return DataReturn('请选择核销员', -1); - } $result = \app\plugins\vr_ticket\service\TicketService::verifyTicket($ticket_code, $verifier_id); return DataReturn($result['msg'], $result['code'], $result['data'] ?? []); @@ -429,6 +464,10 @@ class Admin extends Common */ public function TicketExport() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -476,6 +515,10 @@ class Admin extends Common */ public function VerifierList() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $where = []; $keywords = input('keywords', '', null, 'trim'); @@ -522,6 +565,10 @@ class Admin extends Common */ public function VerifierSave() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $id = input('id', 0, 'intval'); if ((request()->isAjax() && request()->isPost())) { @@ -582,6 +629,10 @@ class Admin extends Common */ public function VerifierDelete() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -620,6 +671,10 @@ class Admin extends Common */ public function VenueList() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $where = []; $name = input('name', '', null); @@ -672,6 +727,10 @@ class Admin extends Common */ public function VenueSave() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $id = input('id', 0, 'intval'); if ((request()->isAjax() && request()->isPost())) { @@ -857,6 +916,10 @@ class Admin extends Common */ public function VenueDelete() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -913,6 +976,10 @@ class Admin extends Common public function VenueEnable() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } if (!(request()->isAjax() && request()->isPost())) { return DataReturn('非法请求', -1); } @@ -945,6 +1012,10 @@ class Admin extends Common */ public function VerificationList() { + // M-06: 权限校验 + if (empty(session('admin_id'))) { + return DataReturn('无权限访问', -1); + } $where = []; $keywords = input('keywords', '', null, 'trim');