ThinkPHP统一登录鉴权中间件需注册在app/middleware.php的'http'数组中SessionInit之后,handle方法内先校验session('user_id'),未登录按请求类型返回JSON错误或重定向,登录后注入user_id属性并放行,白名单路径提前放过。

ThinkPHP 用中间件做统一登录鉴权,核心是把「用户有没有登录」这件事,在控制器执行前就判清楚,并把用户信息可靠地透传下去。不依赖 Session 自动加载、不硬编码校验逻辑、不放在路由解析之前——这三点踩准了,基本就稳了。
中间件注册位置必须对
在 app/middleware.php 的 'http' => [] 数组里,把你的鉴权中间件(比如 app\middleware\CheckLogin::class)加在 SessionInit::class 之后、其他权限类之前。不能放太靠前,否则 $request->session() 还没初始化,session('user_id') 永远为空;也不能放太靠后,比如排在已有鉴权中间件后面,容易重复拦截或漏掉关键判断。
handle 方法里只做三件事
在中间件的 handle() 方法中,聚焦完成以下动作:
- 先调
$request->session()->get('user_id')或session('user_id')判断是否已登录;没值就重定向到登录页:return redirect('/login')->with('msg', '请先登录'); - 登录了,就把用户 ID(或完整用户数据)注入请求:
$request = $request->withAttribute('user_id', $uid);,后续控制器可用$this->request->attr('user_id')拿到 - 最后别忘了放行:
return $next($request);
别在构造函数里查用户
中间件的 __construct() 执行时,$request 对象还没绑定上下文,$request->session() 可能不可用,Auth::check() 也大概率返回 false。所有用户判断和注入操作,必须写在 handle() 方法里,且确保它在 Session 初始化之后运行。
立即学习“PHP免费学习笔记(深入)”;
白名单路径要提前放过
登录页、验证码、注册、健康检查这些接口不能被拦。可以在中间件开头加判断:
- 用
$request->url()获取当前路径,比如/api/login或/public/verify - 配置一个免鉴权数组:
$whitelist = ['/login', '/api/register', '/captcha']; - 匹配成功就直接
return $next($request);,跳过后续校验
响应格式按场景自动适配
如果是 API 请求(Accept: application/json),未登录时不该跳转,而应返回 JSON 错误:
- 检查
$request->header('accept')是否含json - 是则返回:
return json(['code' => 401, 'msg' => '未登录'])->code(401); - 否则走重定向逻辑,兼顾后台页面和接口调用两种场景



















