thinkphp本身不提供二级域名权限控制,需通过中间件在请求进入控制器前校验域名:先启用子域名部署并确保http_host正确传递,再创建中间件读取$request->domain()与配置白名单严格比对,不匹配则返回403;配合多应用绑定可增强隔离性。

ThinkPHP 本身不提供“二级域名权限控制”这个内置功能,所谓限制特定域名访问后台模块,本质是在请求进入控制器前,根据当前域名做拦截判断。核心思路是:域名路由分组 ≠ 权限控制,必须配合中间件主动校验。
一、先确保二级域名能被正确识别
如果 admin.example.com 访问时直接跳首页或报 404,说明框架根本没识别到这个子域名,后续拦截无从谈起。需确认以下配置已生效:
- 在 config/app.php 中启用子域名部署:
'sub_domain_deploy' => true(TP5.1/6)或'url_domain_deploy' => true(TP6+ 推荐) - 配置子域名映射规则,例如:
'sub_domain_rules' => ['admin' => 'admin'](TP5.1)或使用Route::domain('admin', ...)显式绑定(TP6+) - Nginx/Apache 必须正确传递
HTTP_HOST头;反向代理环境下,需加fastcgi_param HTTP_HOST $host; - 本地测试时,
localhost和127.0.0.1需单独加入白名单或映射规则,不能依赖泛匹配
二、用中间件实现精准域名拦截
这是最可靠、最易维护的方式。所有请求统一经过中间件校验,避免在每个控制器里重复写逻辑。
- 创建中间件:
php think make:middleware CheckAdminDomain - 在
handle()方法中获取标准化域名:$host = $request->domain();(TP6.1+ 推荐,自动去端口、转小写) - 从配置文件读取白名单,例如 config/app.php 加:
'admin_domains' => ['admin.example.com', 'manage.example.com'] - 严格比对:
if (!in_array($host, config('app.admin_domains'))) { return response('', 403)->code(403); } - 把该中间件注册为全局中间件,并放在队列最前面,确保它在路由匹配前执行
三、配合多应用模式更安全
若后台模块已独立为 app/admin/ 应用,可进一步通过域名绑定 + 应用隔离强化控制:
- 启用自动多应用:
'auto_multi_app' => true - 在
config/app.php的domain_bind中明确绑定:'admin.example.com' => 'admin' - 此时即使有人绕过中间件,访问
http://other.com/admin/login也不会命中 admin 应用(除非其他域名也绑定了 admin) - 再叠加中间件校验,形成双重保障:先路由定向,再权限拦截
四、注意常见陷阱
很多“配置失败”其实不是代码问题,而是环境或理解偏差导致的:
-
Route::domain('admin', ...) 只负责路由分发,不阻止其他域名访问相同路径 —— 比如
localhost/user/list仍可能触发 admin 路由,必须靠中间件堵住 - 不要用
strpos($host, 'admin')这类模糊匹配,badadmin.example.com会被误放行;必须用完全匹配或明确的子域名后缀判断 - HTTPS 或代理环境下,
$_SERVER['HTTP_HOST']可能是localhost或 IP,优先用$request->domain(),必要时补充$request->header('x-forwarded-host') - CLI 命令行运行时
$request->domain()可能为空,中间件中要加空值判断,避免报错中断
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











