thinkphp域名绑定后需通过中间件手动拦截非法域名访问。在中间件中获取$request->host(),比对配置白名单,不匹配则返回403;注意代理、https及环境差异导致的host异常,域名路由分组不等于权限控制。

ThinkPHP 域名绑定后如何做权限拦截
ThinkPHP 本身不提供“域名级权限控制”这个功能模块,它只支持基于 Route::domain() 的域名路由绑定。所谓“域名鉴权”,本质是:在请求进入控制器前,根据当前请求的 $_SERVER['HTTP_HOST'](或 Request::domain())判断是否允许访问该域名下的全部或部分资源。这不是权限系统自带能力,而是需要你手动拦截。
在中间件里读取域名并拒绝非法请求
这是最直接、最可控的做法。ThinkPHP 6+ 推荐用中间件统一处理入口校验,避免每个控制器都重复判断。
- 创建中间件:
php think make:middleware CheckDomainAuth - 在
handle()方法中获取当前域名:$host = $request->host();或更稳妥地用$request->header('host') - 配置白名单域名数组(建议从配置文件读取,如
config/domain.php),例如:return ['admin.example.com', 'api.example.com']; - 若
$host不在白名单中,直接返回 403:return response('Forbidden', 403); - 注意:HTTPS 下某些代理可能让
host变成localhost或 IP,需结合$request->isSsl()和$request->server('HTTP_X_FORWARDED_HOST')做兼容
配合路由域名分组时的常见陷阱
很多人用 Route::domain('admin.example.com') 分组后,误以为只有这个域名能访问里面定义的路由 —— 实际上,只要请求 URL 路径匹配,任何域名(包括 localhost、127.0.0.1)都能触发该路由,除非你额外拦截。
- 域名路由分组只是“路由匹配规则”,不是“访问控制开关”
- 如果你在
admin.example.com分组里写了Route::get('user/list', 'Admin/User/list'),那么访问http://localhost/user/list依然可能成功(取决于其他路由是否冲突) - 必须搭配中间件或控制器基类中的
initialize()检查,否则域名路由分组形同虚设 - ThinkPHP 5.1 中
Route::domain()不支持通配符子域名(如*.example.com),TP6+ 才支持Route::domain('{name}.example.com'),但变量捕获后仍需在中间件里校验$name是否合法
要不要把域名权限和 RBAC 权限系统打通?
可以,但通常没必要。域名控制属于“访问入口层”,RBAC 属于“功能操作层”,二者粒度和职责不同。强行合并容易导致逻辑混乱。
- 比如
admin.example.com对应后台管理角色,shop.example.com对应商户角色 —— 这种映射适合用中间件 + 配置表维护,而不是塞进auth_rule表 - 如果真要联动,建议只在中间件里根据域名设置一个全局标识:
Session::set('domain_role', 'admin'),后续 RBAC 判断时读取该标识扩展条件,而不是改写核心权限验证逻辑 - 特别注意:域名可被客户端伪造(如修改 Host 请求头),所以绝不能仅靠域名决定用户身份或跳过登录校验
真正容易被忽略的是环境差异:开发时用 localhost 或 127.0.0.1,测试环境用二级域名,生产又可能是泛解析子域名 —— 所有这些场景下的 host 解析逻辑都要覆盖到,否则上线就 403。别只测“看起来对”的那个域名。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











