diff --git a/app/admin/controller/Advert.php b/app/admin/controller/Advert.php index 7f20c21..b404f10 100755 --- a/app/admin/controller/Advert.php +++ b/app/admin/controller/Advert.php @@ -92,10 +92,7 @@ class Advert extends Base if (empty($data['url_link'])) { return $this->renderError("请输入跳转链接"); } - // 简单的URL格式验证 - if (!filter_var($data['url_link'], FILTER_VALIDATE_URL)) { - return $this->renderError("请输入有效的URL地址,必须包含http://或https://"); - } + } } @@ -172,13 +169,10 @@ class Advert extends Base } } if ($data['ttype'] == 5) { - if (empty($data['url_link'])) { + if (empty($data['url'])) { return $this->renderError("请输入跳转链接"); } - // 简单的URL格式验证 - if (!filter_var($data['url_link'], FILTER_VALIDATE_URL)) { - return $this->renderError("请输入有效的URL地址,必须包含http://或https://"); - } + } } diff --git a/app/admin/middleware.php b/app/admin/middleware.php index c76871d..ed83747 100755 --- a/app/admin/middleware.php +++ b/app/admin/middleware.php @@ -5,5 +5,7 @@ use think\facade\Session; use think\middleware\SessionInit; return [ - \think\middleware\SessionInit::class + \think\middleware\SessionInit::class, + # 域名绑定 + \app\admin\middleware\DomainBind::class ]; diff --git a/app/admin/middleware/DomainBind.php b/app/admin/middleware/DomainBind.php new file mode 100644 index 0000000..66925c3 --- /dev/null +++ b/app/admin/middleware/DomainBind.php @@ -0,0 +1,220 @@ +host(); + + // 获取当前请求路径 + $path = $request->pathinfo(); + + // 白名单路径检查 - 不需要验证域名的路径 + $whitelistPaths = $this->getWhitelistPaths(); + foreach ($whitelistPaths as $whitePath) { + // 支持简单的路径匹配,如 'notify/*' 匹配所有通知路径 + if ($this->pathMatch($whitePath, $path)) { + // 白名单路径,跳过域名检查 + \think\facade\Log::info('白名单路径访问: ' . $path . ', 域名: ' . $domain); + return $next($request); + } + } + + // 检查域名是否允许 + if (!$this->checkDomain($domain)) { + // 记录被拒绝的请求 + \think\facade\Log::warning('域名访问被拒绝: ' . $domain . ', 路径: ' . $path); + return $this->error('域名未授权,无法访问', 403); + } + + // 域名允许,记录请求信息(可选,仅用于调试) + \think\facade\Log::info('域名访问通过: ' . $domain . ', 路径: ' . $path); + + // 域名允许,继续处理请求 + return $next($request); + } + + /** + * 检查域名是否在允许列表中 + * + * @param string $domain 请求域名 + * @return bool 是否允许 + */ + protected function checkDomain($domain) + { + // 获取所有允许的域名 + $allowedDomains = $this->getAllowedDomains(); + + // 如果没有设置允许的域名,默认放行所有域名 + if (empty($allowedDomains)) { + return true; + } + + // 检查域名是否在允许列表中 + foreach ($allowedDomains as $allowedDomain) { + // 支持通配符匹配,例如 *.example.com + if ($this->domainMatch($allowedDomain, $domain)) { + return true; + } + } + + // 域名不在允许列表中 + return false; + } + + /** + * 获取所有允许的域名 + * + * @return array 允许的域名列表 + */ + protected function getAllowedDomains() + { + $allowedDomains = []; + + // 1. 从配置文件中获取额外允许的域名 + try { + $configDomains = Config::get('admin.api_domains', []); + if (!empty($configDomains) && is_array($configDomains)) { + foreach ($configDomains as $d) { + $d = trim($d); + if (!empty($d) && !in_array($d, $allowedDomains)) { + $allowedDomains[] = $d; + } + } + } + } catch (\Exception $e) { + // 配置获取失败,记录日志 + \think\facade\Log::error('获取API域名配置失败: ' . $e->getMessage()); + } + + // 3. 记录可用域名到日志,用于调试 + // \think\facade\Log::info('允许的域名列表: ' . json_encode($allowedDomains)); + + return $allowedDomains; + } + + + /** + * 检查域名是否匹配 + * + * @param string $pattern 配置中的域名模式 + * @param string $domain 当前请求的域名 + * @return bool 是否匹配 + */ + protected function domainMatch($pattern, $domain) + { + // 完全匹配 + if (strtolower($pattern) === strtolower($domain)) { + return true; + } + + // 通配符匹配 (例如: *.example.com) + if (strpos($pattern, '*') !== false) { + $pattern = str_replace('*', '.*', $pattern); + $pattern = '/^' . str_replace('.', '\.', $pattern) . '$/i'; + return preg_match($pattern, $domain); + } + + return false; + } + + /** + * 返回错误信息 + * + * @param string $msg 错误信息 + * @param int $code 错误码 + * @return \think\Response + */ + protected function error($msg, $code = 0) + { + $result = [ + 'status' => $code, + 'msg' => $msg, + 'data' => null + ]; + + $response = Response::create($result, 'json', $code); + throw new HttpResponseException($response); + } + + /** + * 中间件结束调度 + * + * @param \think\Response $response + * @return void + */ + public function end(\think\Response $response) + { + // 可以在响应发送前进行一些后置处理 + } + + /** + * 获取路径白名单 + * + * @return array 白名单路径列表 + */ + protected function getWhitelistPaths() + { + // 1. 默认白名单路径(如支付回调通知等) + $defaultWhitelist = [ + 'notify/*', // 支付回调等通知 + 'health', // 健康检查 + 'debug', // 调试接口 + ]; + + // 2. 从配置文件中获取白名单路径 + try { + $configWhitelist = Config::get('api.whitelist_paths', []); + if (!empty($configWhitelist) && is_array($configWhitelist)) { + return array_merge($defaultWhitelist, $configWhitelist); + } + } catch (\Exception $e) { + \think\facade\Log::error('获取API白名单路径配置失败: ' . $e->getMessage()); + } + + return $defaultWhitelist; + } + + /** + * 路径匹配检查 + * + * @param string $pattern 白名单路径模式 + * @param string $path 请求路径 + * @return bool 是否匹配 + */ + protected function pathMatch($pattern, $path) + { + // 完全匹配 + if ($pattern === $path) { + return true; + } + + // 通配符匹配 (例如: 'notify/*') + if (strpos($pattern, '*') !== false) { + $pattern = str_replace('*', '.*', $pattern); + $pattern = '/^' . str_replace('/', '\/', $pattern) . '$/i'; + return preg_match($pattern, $path); + } + + return false; + } +} \ No newline at end of file diff --git a/app/admin/view/Advert/add.html b/app/admin/view/Advert/add.html index 6ee3b47..4844712 100755 --- a/app/admin/view/Advert/add.html +++ b/app/admin/view/Advert/add.html @@ -53,7 +53,7 @@ diff --git a/app/admin/view/Advert/edit.html b/app/admin/view/Advert/edit.html index bbae495..1657734 100755 --- a/app/admin/view/Advert/edit.html +++ b/app/admin/view/Advert/edit.html @@ -53,7 +53,7 @@ diff --git a/app/api/controller/FuLiWu.php b/app/api/controller/FuLiWu.php index 81e0aaf..b0744ed 100644 --- a/app/api/controller/FuLiWu.php +++ b/app/api/controller/FuLiWu.php @@ -327,7 +327,7 @@ class FuLiWu extends Base $goods_id = $item['goods_id']; $goods = GoodsModel::where('id', '=', $goods_id)->find(); $item['goods_title'] = $goods['title']; - $item['create_time'] = date('Y-m-d H:i', $item['addtime']); + $item['create_time'] = date('Y-m-d H:i', $goods['open_time']); } } diff --git a/app/api/controller/Goods.php b/app/api/controller/Goods.php index ae32567..03d2897 100755 --- a/app/api/controller/Goods.php +++ b/app/api/controller/Goods.php @@ -88,7 +88,8 @@ class Goods extends Base } elseif ($type_str == 16) { $whe[] = ['type', '=', 16]; } else { - $whe[] = ['type', 'not in', [4, 10, 15]]; + // $whe[] = ['type', 'not in', [4, 10, 15]]; + $whe[] = ['type', 'in', 2, 6, 8, 16]; } $user_id = $this->getUserId(); diff --git a/app/api/controller/Index.php b/app/api/controller/Index.php index 92f9a84..ec7cf56 100755 --- a/app/api/controller/Index.php +++ b/app/api/controller/Index.php @@ -24,11 +24,11 @@ class Index extends Base public function index(Request $request) { #首页轮播图 - $advert = Advert::field('imgurl,ttype,coupon_id,goods_id')->where(['type' => 1])->order('sort desc,id desc')->select(); + $advert = Advert::field('imgurl,ttype,coupon_id,goods_id,url')->where(['type' => 1])->order('sort desc,id desc')->select(); foreach ($advert as &$advert_value) { $advert_value['imgurl'] = imageUrl($advert_value['imgurl']); } - $tuijian = Advert::field('imgurl,ttype,coupon_id,goods_id')->where(['type' => 5])->order('sort desc,id desc')->select(); + $tuijian = Advert::field('imgurl,ttype,coupon_id,goods_id,url')->where(['type' => 5])->order('sort desc,id desc')->select(); foreach ($tuijian as &$advert_value) { $advert_value['imgurl'] = imageUrl($advert_value['imgurl']); } diff --git a/app/api/middleware.php b/app/api/middleware.php index d55c413..3d07bac 100755 --- a/app/api/middleware.php +++ b/app/api/middleware.php @@ -1,6 +1,8 @@ host(); + + // 获取当前请求路径 + $path = $request->pathinfo(); + + // 白名单路径检查 - 不需要验证域名的路径 + $whitelistPaths = $this->getWhitelistPaths(); + foreach ($whitelistPaths as $whitePath) { + // 支持简单的路径匹配,如 'notify/*' 匹配所有通知路径 + if ($this->pathMatch($whitePath, $path)) { + // 白名单路径,跳过域名检查 + \think\facade\Log::info('白名单路径访问: ' . $path . ', 域名: ' . $domain); + return $next($request); + } + } + + // 检查域名是否允许 + if (!$this->checkDomain($domain)) { + // 记录被拒绝的请求 + \think\facade\Log::warning('域名访问被拒绝: ' . $domain . ', 路径: ' . $path); + return $this->error('域名未授权,无法访问', 403); + } + + // 域名允许,记录请求信息(可选,仅用于调试) + \think\facade\Log::info('域名访问通过: ' . $domain . ', 路径: ' . $path); + + // 域名允许,继续处理请求 + return $next($request); + } + + /** + * 检查域名是否在允许列表中 + * + * @param string $domain 请求域名 + * @return bool 是否允许 + */ + protected function checkDomain($domain) + { + // 获取所有允许的域名 + $allowedDomains = $this->getAllowedDomains(); + + // 如果没有设置允许的域名,默认放行所有域名 + if (empty($allowedDomains)) { + return true; + } + + // 检查域名是否在允许列表中 + foreach ($allowedDomains as $allowedDomain) { + // 支持通配符匹配,例如 *.example.com + if ($this->domainMatch($allowedDomain, $domain)) { + return true; + } + } + + // 域名不在允许列表中 + return false; + } + + /** + * 获取所有允许的域名 + * + * @return array 允许的域名列表 + */ + protected function getAllowedDomains() + { + $allowedDomains = []; + // 1. 从配置文件中获取额外允许的域名 + try { + $configDomains = Config::get('api.api_domains', []); + if (!empty($configDomains) && is_array($configDomains)) { + foreach ($configDomains as $d) { + $d = trim($d); + if (!empty($d) && !in_array($d, $allowedDomains)) { + $allowedDomains[] = $d; + } + } + } + } catch (\Exception $e) { + // 配置获取失败,记录日志 + \think\facade\Log::error('获取API域名配置失败: ' . $e->getMessage()); + } + + // 3. 记录可用域名到日志,用于调试 + // \think\facade\Log::info('允许的域名列表: ' . json_encode($allowedDomains)); + + return $allowedDomains; + } + + /** + * 获取所有小程序配置 + * + * @return array 小程序配置列表 + */ + protected function getMiniprogramConfigs() + { + // 从配置中获取小程序配置 + $miniprogramSetting = \think\facade\Config::get('miniprogram_setting', []); + + // 如果配置中没有小程序列表,则尝试从数据库或缓存获取 + if (empty($miniprogramSetting) || empty($miniprogramSetting['miniprograms'])) { + $miniprogramSetting = getConfig('miniprogram_setting'); + } + + return $miniprogramSetting['miniprograms'] ?? []; + } + + /** + * 检查域名是否匹配 + * + * @param string $pattern 配置中的域名模式 + * @param string $domain 当前请求的域名 + * @return bool 是否匹配 + */ + protected function domainMatch($pattern, $domain) + { + // 完全匹配 + if (strtolower($pattern) === strtolower($domain)) { + return true; + } + + // 通配符匹配 (例如: *.example.com) + if (strpos($pattern, '*') !== false) { + $pattern = str_replace('*', '.*', $pattern); + $pattern = '/^' . str_replace('.', '\.', $pattern) . '$/i'; + return preg_match($pattern, $domain); + } + + return false; + } + + /** + * 返回错误信息 + * + * @param string $msg 错误信息 + * @param int $code 错误码 + * @return \think\Response + */ + protected function error($msg, $code = 0) + { + $result = [ + 'status' => $code, + 'msg' => $msg, + 'data' => null + ]; + + $response = Response::create($result, 'json', $code); + throw new HttpResponseException($response); + } + + /** + * 中间件结束调度 + * + * @param \think\Response $response + * @return void + */ + public function end(\think\Response $response) + { + // 可以在响应发送前进行一些后置处理 + } + + /** + * 获取路径白名单 + * + * @return array 白名单路径列表 + */ + protected function getWhitelistPaths() + { + // 1. 默认白名单路径(如支付回调通知等) + $defaultWhitelist = [ + 'notify/*', // 支付回调等通知 + 'health', // 健康检查 + 'debug', // 调试接口 + ]; + + // 2. 从配置文件中获取白名单路径 + try { + $configWhitelist = Config::get('api.whitelist_paths', []); + if (!empty($configWhitelist) && is_array($configWhitelist)) { + return array_merge($defaultWhitelist, $configWhitelist); + } + } catch (\Exception $e) { + \think\facade\Log::error('获取API白名单路径配置失败: ' . $e->getMessage()); + } + + return $defaultWhitelist; + } + + /** + * 路径匹配检查 + * + * @param string $pattern 白名单路径模式 + * @param string $path 请求路径 + * @return bool 是否匹配 + */ + protected function pathMatch($pattern, $path) + { + // 完全匹配 + if ($pattern === $path) { + return true; + } + + // 通配符匹配 (例如: 'notify/*') + if (strpos($pattern, '*') !== false) { + $pattern = str_replace('*', '.*', $pattern); + $pattern = '/^' . str_replace('/', '\/', $pattern) . '$/i'; + return preg_match($pattern, $path); + } + + return false; + } +} \ No newline at end of file diff --git a/config/api.php b/config/api.php new file mode 100644 index 0000000..6ab0b80 --- /dev/null +++ b/config/api.php @@ -0,0 +1,32 @@ + [ + 'localhost', + '127.0.0.1', + '192.168.1.56', + 'manghe.zpc-xy.com' + // 添加其他允许的域名 + // 'example.com', + // '*.example.com', + ], + # 后台允许访问的域名 + 'admin_domains' => [ + 'localhost', + '127.0.0.1', + '192.168.1.56', + 'manghe.zpc-xy.com' + // 添加其他允许的域名 + // 'example.com', + // '*.example.com', + ], + // 不需要验证域名的白名单路径 + 'whitelist_paths' => [ + 'notify/*', // 支付回调等通知 + 'health', // 健康检查 + 'ping', // 服务可用性检查 + 'debug', // 调试接口 + 'wechat/callback', // 微信回调 + ], +]; \ No newline at end of file