312
This commit is contained in:
parent
b679b9396b
commit
80cbb3d874
|
|
@ -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://");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
];
|
||||
|
|
|
|||
220
app/admin/middleware/DomainBind.php
Normal file
220
app/admin/middleware/DomainBind.php
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
<?php
|
||||
/**
|
||||
* 域名绑定中间件
|
||||
* 用于检查请求域名是否在允许的列表中
|
||||
*/
|
||||
|
||||
namespace app\admin\middleware;
|
||||
|
||||
use think\facade\Config;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
|
||||
|
||||
class DomainBind
|
||||
{
|
||||
/**
|
||||
* 处理请求
|
||||
*
|
||||
* @param \think\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \think\Response
|
||||
*/
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
// 获取当前请求域名
|
||||
$domain = $request->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;
|
||||
}
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
<div class="layui-form-item url_link">
|
||||
<label class="layui-form-label">跳转链接</label>
|
||||
<div class="layui-input-inline" style="width: 400px;">
|
||||
<input type="text" name="url_link" value="" lay-verify="required" placeholder="请输入完整的URL地址" autocomplete="off" class="layui-input">
|
||||
<input type="text" name="url" value="" lay-verify="required" placeholder="请输入完整的URL地址" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">例如: /pages/shouye/index</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
<div class="layui-form-item url_link">
|
||||
<label class="layui-form-label">跳转链接</label>
|
||||
<div class="layui-input-inline" style="width: 400px;">
|
||||
<input type="text" name="url_link" value="{$data['url_link']}" lay-verify="required" placeholder="请输入完整的URL地址" autocomplete="off" class="layui-input">
|
||||
<input type="text" name="url" value="{$data['url']}" lay-verify="required" placeholder="请输入完整的URL地址" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-mid layui-word-aux">例如: /pages/shouye/index</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
// 域名绑定检查
|
||||
\app\api\middleware\DomainBind::class,
|
||||
//h5跨域
|
||||
\app\api\middleware\Allow::class,
|
||||
|
||||
|
|
|
|||
236
app/api/middleware/DomainBind.php
Normal file
236
app/api/middleware/DomainBind.php
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
<?php
|
||||
/**
|
||||
* 域名绑定中间件
|
||||
* 用于检查请求域名是否在允许的列表中
|
||||
*/
|
||||
|
||||
namespace app\api\middleware;
|
||||
|
||||
use think\facade\Config;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
use app\common\helper\MiniprogramHelper;
|
||||
|
||||
class DomainBind
|
||||
{
|
||||
/**
|
||||
* 处理请求
|
||||
*
|
||||
* @param \think\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \think\Response
|
||||
*/
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
// 获取当前请求域名
|
||||
$domain = $request->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;
|
||||
}
|
||||
}
|
||||
32
config/api.php
Normal file
32
config/api.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
// API模块配置
|
||||
return [
|
||||
# 接口允许访问的域名
|
||||
'api_domains' => [
|
||||
'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', // 微信回调
|
||||
],
|
||||
];
|
||||
Loading…
Reference in New Issue
Block a user