如何通过ThinkPHP中间件设置特定域名访问限制?

2026-04-30 16:002阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计907个文字,预计阅读时间需要4分钟。

如何通过ThinkPHP中间件设置特定域名访问限制?

ThinkPHP 6 的中间件中,可以使用 `$request` 对象来获取请求信息。以下是使用 `$request` 的基本示例:

  • 推荐用 $request->domain()(TP6.1+),它自动剥离端口、转小写、处理 IP 地址,返回干净域名
  • 如果用 $request->header('host'),要手动 explode(':', ...)[0] 去端口,否则 localhost:8000localhost 会被当成两个不同域名
  • 本地开发时,浏览器常通过 127.0.0.1localhost 访问,但服务器部署后真实域名才生效,测试务必在同环境验证

如何配置白名单域名并做精确匹配

硬编码域名列表容易出错,建议把白名单写进配置文件(如 config/app.php'allowed_domains' => ['api.example.com', 'admin.example.com']),中间件里读取后做严格比对。别用 strpos() 或模糊匹配——example.com 会误放行 badexample.com

  • in_array($request->domain(), config('app.allowed_domains')) 做完全匹配
  • 如果需要支持子域名通配(如 *.example.com),得自己写判断逻辑:str_ends_with($host, '.example.com') || $host === 'example.com'
  • 注意 www.example.comexample.com 是两个域名,白名单里必须都写上,或者统一重定向到主域名

拦截失败时返回什么状态码和响应

直接 return response('', 403) 虽然能拦住,但前端可能收不到明确提示;返回 JSON 更利于前后端协作。但别返回 404——这不是资源不存在,而是权限拒绝。

  • 生产环境用 return json(['code' => 403, 'msg' => 'Forbidden domain'])->code(403)
  • 避免返回完整错误堆栈(尤其开启调试模式时),防止暴露服务器信息
  • 如果项目用了 CORS,记得在中间件里提前设置响应头($response->header('Access-Control-Allow-Origin', '*')),否则跨域请求可能卡在预检阶段就失败,让你误以为拦截没生效

为什么有些请求绕过了域名检查

常见漏网原因不是代码写错,而是中间件注册位置不对。ThinkPHP 的中间件执行顺序很关键:如果域名检查中间件放在路由之后(比如在 app/middleware.php 里写在了 AllowCrossDomain::class 后面),某些静态资源或未定义路由可能根本不会走到你这步。

立即学习“PHP免费学习笔记(深入)”;

  • 必须把域名拦截中间件加到全局中间件数组开头(app/middleware.php$middleware 第一项)
  • 确认没在控制器或路由闭包里用 ->middleware([]) 覆盖掉全局中间件
  • CLI 请求(如命令行运行任务)没有 Host 头,$request->domain() 返回空字符串,白名单里没配空值就会被拦——需单独处理:if (empty($host)) { return $next($request); }
域名拦截看着简单,真正上线后最容易栽在 Host 头解析不一致、中间件加载顺序、以及 CLI/HTTP 混用场景下的空 host 判断上。测的时候别只刷浏览器,curl 带 -H 'Host: xxx' 手动模拟各种头才是真验活。
标签:PHPThinkPHP

本文共计907个文字,预计阅读时间需要4分钟。

如何通过ThinkPHP中间件设置特定域名访问限制?

ThinkPHP 6 的中间件中,可以使用 `$request` 对象来获取请求信息。以下是使用 `$request` 的基本示例:

  • 推荐用 $request->domain()(TP6.1+),它自动剥离端口、转小写、处理 IP 地址,返回干净域名
  • 如果用 $request->header('host'),要手动 explode(':', ...)[0] 去端口,否则 localhost:8000localhost 会被当成两个不同域名
  • 本地开发时,浏览器常通过 127.0.0.1localhost 访问,但服务器部署后真实域名才生效,测试务必在同环境验证

如何配置白名单域名并做精确匹配

硬编码域名列表容易出错,建议把白名单写进配置文件(如 config/app.php'allowed_domains' => ['api.example.com', 'admin.example.com']),中间件里读取后做严格比对。别用 strpos() 或模糊匹配——example.com 会误放行 badexample.com

  • in_array($request->domain(), config('app.allowed_domains')) 做完全匹配
  • 如果需要支持子域名通配(如 *.example.com),得自己写判断逻辑:str_ends_with($host, '.example.com') || $host === 'example.com'
  • 注意 www.example.comexample.com 是两个域名,白名单里必须都写上,或者统一重定向到主域名

拦截失败时返回什么状态码和响应

直接 return response('', 403) 虽然能拦住,但前端可能收不到明确提示;返回 JSON 更利于前后端协作。但别返回 404——这不是资源不存在,而是权限拒绝。

  • 生产环境用 return json(['code' => 403, 'msg' => 'Forbidden domain'])->code(403)
  • 避免返回完整错误堆栈(尤其开启调试模式时),防止暴露服务器信息
  • 如果项目用了 CORS,记得在中间件里提前设置响应头($response->header('Access-Control-Allow-Origin', '*')),否则跨域请求可能卡在预检阶段就失败,让你误以为拦截没生效

为什么有些请求绕过了域名检查

常见漏网原因不是代码写错,而是中间件注册位置不对。ThinkPHP 的中间件执行顺序很关键:如果域名检查中间件放在路由之后(比如在 app/middleware.php 里写在了 AllowCrossDomain::class 后面),某些静态资源或未定义路由可能根本不会走到你这步。

立即学习“PHP免费学习笔记(深入)”;

  • 必须把域名拦截中间件加到全局中间件数组开头(app/middleware.php$middleware 第一项)
  • 确认没在控制器或路由闭包里用 ->middleware([]) 覆盖掉全局中间件
  • CLI 请求(如命令行运行任务)没有 Host 头,$request->domain() 返回空字符串,白名单里没配空值就会被拦——需单独处理:if (empty($host)) { return $next($request); }
域名拦截看着简单,真正上线后最容易栽在 Host 头解析不一致、中间件加载顺序、以及 CLI/HTTP 混用场景下的空 host 判断上。测的时候别只刷浏览器,curl 带 -H 'Host: xxx' 手动模拟各种头才是真验活。
标签:PHPThinkPHP