ThinkPHP 6.x 移除了内置 Auth 类,推荐用中间件实现鉴权:路由级 RBAC 校验需映射路由名到权限、JWT/OAuth2 应复用成熟库解析 Token 并挂载到 Request,同时注意 CLI 绕过和多守卫切换。
ThinkPHP 6.x 中为什么不用 Auth 而该用
或自建中间件
ThinkPHP 官方从 6.0 开始移除了内置的
类(即 TP5 的
),所以直接 require 或 new Auth 会报
。社区维护的
库虽可接入,但它基于 RBAC 且强耦合数据库结构,若你已有用户/角色/权限表,或想对接 OAuth2、JWT、CAS 等第三方鉴权服务,硬套
反而增加转换成本。
更务实的做法是:绕过“Auth 系统集成”这个概念,直接在中间件中完成鉴权逻辑。关键不是“怎么装 Auth”,而是“在哪验、验什么、不通过怎么拦”。
如何在中间件里做路由级权限校验(RBAC 场景)
假设你已有三张表:
、
、
,并已通过关联查出当前用户拥有的权限标识(如
、
)。校验应发生在请求进入控制器前,且只对需要保护的路由生效。
新建中间件
,
方法中获取当前路由名(
)或规则路径(
)
从 Session 或 Token 解析出用户 ID,查库得到该用户所有权限字符串数组(避免每次查完整角色树,缓存到 Redis 更稳)
定义权限映射表:把路由名映射到所需权限,例如
,或用正则匹配(
)
不匹配时调用
,别用
——中间件里跳转易丢失原始请求方法和参数
示例片段:
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
对接 JWT/OAuth2 第三方鉴权时,Token 解析和刷新怎么做
如果你的前端用
传 token,后端不该自己实现 JWT 签名校验,而应复用成熟库(如
),重点在于:何时解析、解析结果放哪、失效了怎么处理。
中间件中用
提取,去掉
前缀
用
验签并捕获
、
,对应返回 401 或 403
解出的 payload(如
、
)建议挂到
,后续控制器可直接用
不要在中间件里自动刷新 token:刷新需客户端主动发起
请求,且必须校验 refresh_token(通常存在 HttpOnly Cookie 或独立 header)
容易被忽略的两个边界点:多守卫切换与 CLI 命令绕过
TP6 的
(注意不是旧版
)其实是守卫(Guard)机制,比如
守卫用 session,
守卫用 token。但很多人写中间件时默认只查
,却忘了命令行执行
也会走中间件——此时
为空,
守卫可能抛异常。
在中间件开头加判断:
不同模块用不同守卫时,别全局绑定一个
实例;应在中间件内按需调用
或
数据库权限变更后,已登录用户的 session 或 token 不会自动失效——要么加版本号字段做强制登出,要么在每次鉴权时查一次权限缓存是否过期
think-authAuththink\AuthClass "think\Auth" not foundthink-auththink-authusersrolespermissionsuser:editorder:deleteapp/middleware/PermissionCheck.phphandle()$request->route()->getName()$request->url(true)['admin.user.edit' => 'user:edit']admin.*.delete → .*:deleteabort(403, 'Forbidden')redirect()// 在 handle() 中
$rule = $request->route()->getName();
$allowed = $this->getPermissions($userId); // 如 ['user:list', 'user:edit']
$required = $this->getRequiredPermission($rule); // 如 'user:edit'
if (!in_array($required, $allowed)) {
abort(403);
}
Authorization: Bearer xxxfirebase/php-jwt$token = $request->header('authorization')Bearer JWT::decode()ExpiredExceptionSignatureInvalidExceptionuidscope$request->attr('user', $payload)$this->request->attr('user')/api/token/refreshauthAuthadminapiauth('api')php think hello$request->header()authif (is_cli()) { return $next($request); }authauth('admin')->check()auth('api')->check()