TP6接口RBAC权限控制的核心是快速准确校验用户对当前接口的访问权限,关键在于路由显式命名(如admin.user.delete)、权限标识严格对齐(点号转斜杠为admin/user/delete)、中间件轻量拦截(查角色缓存而非全量权限)、登录后必须调用Auth::setUser($uid)初始化权限缓存。

TP6 接口权限的 RBAC 控制,核心不是查表次数多不多,而是让每次请求都能快速、准确地判断“当前用户有没有执行这个接口的权限”。关键在于路由命名统一、权限标识对齐、中间件校验轻量、缓存按需加载。
路由必须显式命名并规范格式
所有后台接口路由(尤其是 POST/PUT/DELETE 等操作型接口)都要用 →name() 显式绑定小写+点号分隔的英文标识,例如:
Route::post('admin/user/delete', 'admin.UserController@delete')->name('admin.user.delete');Route::put('api/v1/order/status', 'api.v1.OrderController@changeStatus')->name('api.v1.order.status');
不命名会导致 $request->rule()->getName() 返回空或反射路径(如 app\controller\admin\UserController::delete),Auth::check() 就无法匹配数据库中预设的 admin/user/delete 这类标准权限名。
权限节点表要精准对应接口行为
auth_rule 表中每条记录代表一个可鉴权的最小操作单元,name 字段必须与路由 name 严格对应(点号转斜杠),type 设为 action(区别于菜单的 menu):
- 路由 name 是
admin.user.delete→ 权限 name 存admin/user/delete - 不要混用 HTTP 方法进 name(如
admin.user.delete.post),若需区分方法,单独加method字段存值 - 避免 condition 字段滥用——每次 Auth::check() 都会拼 SQL 执行,易引发全表扫描或注入风险
中间件做轻量拦截,不查全量权限
在 app/middleware/AuthCheck.php 中,只提取当前路由名、转成权限标识、查缓存判断,不查库、不遍历、不拼接参数:
- 用
$routeName = $request->rule()->getName()获取权威路由标识 - 转成权限键:
$permissionKey = str_replace('.', '/', $routeName);(如admin.user.delete→admin/user/delete) - 查角色对应权限缓存:
cache('auth_rule_set_' . $roleId),命中则 in_array 判断,未命中再查库并写入缓存(TTL 建议 30 分钟) - 游客跳登录页,超级管理员直接放行,不参与权限比对
登录后必须调用 Auth::setUser($uid)
这是 TP6 权限失效最常见原因。Auth::check() 默认从 session('think_auth') 读缓存,而该 session 不会自动写入。登录成功后务必立即执行:
Auth::setUser($user['id']);- 若使用多应用(如 admin 和 api 分开),需传 app 参数:
Auth::setUser($uid, 'admin') - 确保中间件中 Auth::check() 的调用上下文与 setUser 一致,否则查的是默认应用下的规则
不复杂但容易忽略。

















