TP6中使用中间件方式设置域名白名单或黑名单

71 阅读1分钟

在 ThinkPHP 6 中实现全局域名过滤(即只允许指定域名访问,拒绝其他域名的请求),可以通过中间件来实现,确保所有请求在进入业务逻辑前先经过域名验证。以下是具体步骤:

步骤 1:创建域名过滤中间件

  1. 首先生成一个中间件文件,执行命令:

    bash

    php think make:middleware DomainFilter
    

    生成的文件路径为:app/middleware/DomainFilter.php

  2. 编辑中间件逻辑,实现域名白名单过滤:

    php

    <?php
    namespace app\middleware;
    
    use think\facade\Request;
    use think\response\Redirect; // 可选,用于跳转
    use think\exception\HttpException;
    
    class DomainFilter
    {
        // 允许访问的域名白名单(不含协议,支持通配符*)
        protected $allowDomains = [
            'example.com',       // 允许主域名
            '*.example.com',     // 允许所有子域名
            'test.com',          // 允许其他域名
        ];
    
        public function handle($request, \Closure $next)
        {
            // 获取当前请求的主机名(不含协议和端口,如:www.example.com)
            $currentHost = Request::host();
    
            // 检查当前域名是否在白名单中
            if (!$this->isAllowed($currentHost)) {
                // 拒绝访问:返回403错误或跳转
                throw new HttpException(403, '禁止访问:无效的域名');
                // 或跳转至指定页面:return redirect('https://example.com/error');
            }
    
            // 验证通过,继续执行后续请求
            return $next($request);
        }
    
        /**
         * 验证当前域名是否在白名单中(支持通配符)
         * @param string $host 当前主机名
         * @return bool
         */
        protected function isAllowed(string $host): bool
        {
            foreach ($this->allowDomains as $allow) {
                // 处理通配符(如 *.example.com 匹配 a.example.com、b.example.com 等)
                $pattern = str_replace(['.', '*'], ['.', '.*'], $allow);
                if (preg_match("/^{$pattern}$/", $host)) {
                    return true;
                }
            }
            return false;
        }
    }
    

步骤 2:注册全局中间件

将中间件添加到全局中间件列表,确保所有请求都经过过滤:

  1. 编辑 app/middleware.php 文件(全局中间件配置):

    php

    <?php
    return [
        // 其他全局中间件...
        \app\middleware\DomainFilter::class, // 添加域名过滤中间件
    ];
    

    注意:中间件执行顺序是数组的顺序,建议将域名过滤放在靠前的位置(如最顶部),避免无效请求进入后续逻辑。

步骤 3:测试验证

  • 使用白名单中的域名访问:请求正常处理。
  • 使用非白名单域名访问:返回 403 错误(或自定义跳转),实现全局域名过滤。

扩展说明

  1. 动态配置白名单:若需要从数据库或配置文件读取白名单,可在中间件的 __construct 方法中加载,例如:

    php

    public function __construct()
    {
        // 从配置文件读取(需在 config 目录下定义 domain.php 配置)
        $this->allowDomains = config('domain.allow_list', []);
    }
    
  2. 排除特定路由:若部分路由不需要过滤(如 API 接口),可在中间件中通过 $request->pathinfo() 判断路径并跳过,例如:

    php

    if (strpos($request->pathinfo(), 'api/') === 0) {
        return $next($request); // 跳过API路由的过滤
    }
    
  3. HTTPS 强制校验:若需要同时限制协议(如只允许 HTTPS),可在中间件中添加协议验证:

    php

    if (!Request::isSsl()) {
        throw new HttpException(403, '请使用HTTPS访问');
    }
    

通过以上方法,即可在 TP6 中实现全局、灵活的域名过滤功能。