thinkphp 7鉴权需路由级显式绑定中间件,按认证→权限顺序注册并调用,中间件中通过$request->getattribute('user')获取用户,白名单放行公共路径,且handle方法必须明确返回响应。

ThinkPHP 7(基于 TP6.3+ 演进,当前稳定版实为 TP6.4,社区常称“TP7”指代最新主干)配置中间件鉴权拦截,核心是「路由级显式绑定 + 中间件职责分离 + 执行顺序可控」。它不依赖控制器注解或全局自动扫描,而是靠你在定义路由时主动挂载,并确保认证与权限中间件按逻辑先后执行。
一、先注册认证中间件,再注册权限中间件
在 config/middleware.php 中,按依赖顺序声明中间件数组:
- 认证中间件(如
CheckAuth)必须排在权限中间件(如CheckPermission)之前 - 两者都应靠前,避免被日志、语言包等中间件隔开
- 不要写成
['app\middleware\CheckAuth', 'app\middleware\CheckPermission']这种裸字符串数组——需确认类存在且可自动加载
示例配置(config/middleware.php):
return [
\app\middleware\ForceHttpsMiddleware::class,
\app\middleware\ValidatePostSize::class,
\app\middleware\ParseJsonBody::class,
\app\middleware\CheckAuth::class, // ← 先完成用户识别并注入 $request->getAttribute('user')
\app\middleware\CheckPermission::class, // ← 再基于用户做路由/操作级判断
\app\middleware\Logger::class, // ← 日志放最后,有完整上下文
];
二、路由组必须显式绑定中间件
路由组本身不带任何权限语义,不写 middleware 就等于没加锁。哪怕路径是 /admin/user/delete,没绑定中间件就拦不住未登录访问。
- 用
->middleware()链式调用,不是注解(@middleware在 TP6+ 默认关闭且不可靠) - 推荐对管理后台统一分组绑定,敏感接口可叠加多层校验
示例(route/app.php):
Route::group('admin', function () {
Route::get('index', 'Admin/Index/index');
Route::get('user/list', 'Admin/User/list');
Route::post('user/delete', 'Admin/User/delete');
})->middleware(['check_auth', 'check_permission']); // ← 必须这里写
// 登录等免鉴权接口,用 withoutMiddleware 显式排除
Route::post('login', 'Auth/Login/login')->withoutMiddleware(['check_auth', 'check_permission']);
三、中间件内正确获取用户和路由信息
别在构造函数里查用户,也别依赖 $request->route()->param()——此时路由尚未解析完成。
- 用户对象应由前置认证中间件注入:
$request->getAttribute('user') - 要取 URL 中的动态参数(如
/article/123的 123),用$request->param('id')或$request->url()->getPath() - 判断是否需要鉴权,建议用路径前缀白名单(如
str_starts_with($path, '/api/public'))快速放行
权限中间件片段示例:
public function handle($request, \Closure $next)
{
$path = $request->url()->getPath();
// 白名单放行
$publicPaths = ['/login', '/captcha', '/api/v1/public'];
if (in_array($path, $publicPaths) || str_starts_with($path, '/static/')) {
return $next($request);
}
$user = $request->getAttribute('user');
if (!$user) {
return redirect('/login')->with('error', '请先登录');
}
$action = $request->controller() . '/' . $request->action();
if (!$this->hasPermission($user, $action)) {
return abort(403, '无权访问');
}
return $next($request);
}
四、确保每个分支都有明确返回值
中间件 handle() 方法必须显式 return,漏掉 return $next($request) 会导致请求静默中断(返回 null 被框架视为终止)。
- 拦截时:返回
redirect()、json()或abort() - 放行时:只有一处
return $next($request),且放在最后 - 禁止使用
echo、die、exit,会破坏框架响应生命周期
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











