ThinkPHP路由组必须显式绑定中间件才能实现权限控制;未绑定则无权限校验,即使路径在admin下也无法拦截未登录访问。
ThinkPHP 路由组怎么配中间件做权限控制
路由组本身不校验权限,必须显式绑定中间件;没绑定就等于裸奔,哪怕路由写在
下也拦不住未登录用户直接访问
。
实操上,要在定义路由组时用
方法挂载鉴权中间件,不是在控制器或全局配置里“顺手加一下”:
是中间件名,需提前在
或注解中注册
中间件返回
(如重定向到登录页)即中断执行,返回
或
才放行
别把中间件名写成类全路径(如
),除非你用的是闭包或数组方式注册
为什么中间件里 $request->route() 取不到路由参数
因为中间件执行时机早于路由解析完成——
返回空或默认值是正常现象,不是代码写错了。
要取 URL 中的动态段(比如
的
),得从
拿,而不是依赖路由对象:
立即学习
“
PHP免费学习笔记(深入)
”;
所有基于路由参数的权限判断(如“只能删自己发的文章”)都得走
或
解析
如果需要完整路由信息(如当前分组名、是否在 admin 下),可用
查当前匹配的路由规则
多个路由组嵌套时中间件执行顺序容易错乱
ThinkPHP 的中间件是“先进后出”压栈执行,外层组的中间件会比内层更早进入、更晚退出——这和直觉相反,导致日志打点、权限叠加逻辑容易出 bug。
比如同时给
组和
子组都绑了
和
,实际执行顺序是:
重复鉴权(如两层都 check_auth)不会报错,但可能多查一次数据库,性能白耗
想让子组跳过父组中间件?不能靠“覆盖”,得用
显式排除:
调试时用
打点,比看日志更准
中间件里 redirect() 后控制器仍执行的坑
常见错误是中间件写了
却没
,结果 PHP 继续往下跑,控制器照常执行,甚至返回 200 + 页面内容,而浏览器收到的是 302 响应头 + 空体——页面白屏或状态错乱。
必须确保中间件里所有分支都有明确返回值:
漏掉
是 ThinkPHP 6+ 最隐蔽的权限失效原因之一
IDE 不会报错,PHP 也不会警告,但行为完全失控
如果中间件逻辑复杂,建议统一用
或早期 return 风格,避免嵌套太深漏写
权限逻辑越往后越容易混进业务判断,比如“编辑文章时检查是否作者”这种,已经不属于路由层该管的事——这时候该交给服务层做,而不是在中间件里拼 SQL 或调模型。
admin//admin/user/deletemiddleware
Route::group('admin', function () {
Route::get('user/list', 'Admin/User/list');
Route::post('user/delete', 'Admin/User/delete');
})->middleware('check_auth'); // ← 必须这里写
check_authapp/middleware.phpResponsenull$next($request)\app\middleware\Auth::classroute()/article/123123$request->param()
public function handle($request, \Closure $next)
{
$id = $request->param('id'); // ← 正确:从请求参数取
// $id = $request->route()->param('id'); // ← 错误:此时 route() 还没解析完
if (!$this->hasPermission($id)) {
return redirect('/403');
}
return $next($request);
}
$request->param()$request->url()$request->rule()api/api/v2/auththrottle
→ api/ 的 auth(先入)
→ api/v2/ 的 auth(再入)
→ api/v2/ 的 throttle(再入)
→ 控制器
← api/v2/ 的 throttle(先出)
← api/v2/ 的 auth(再出)
← api/ 的 auth(最后出)
withoutMiddleware()->withoutMiddleware(['auth'])trace('middleware', 'xxx')redirect()return
public function handle($request, \Closure $next)
{
if (!session('user_id')) {
return redirect('/login'); // ← 必须 return!
}
return $next($request); // ← 这个也不能少
}
returnmatch