thinkphp 6 rbac权限中间件必须注册在app/middleware.php的'http'数组靠后位置,确保路由匹配完成后执行;需通过$request->rule()->getname()获取显式命名的路由名,走用户→角色→权限三级查询,对游客跳登录、超管短路放行,并区分页面与ajax响应格式。

中间件注册位置必须在路由匹配之后
权限校验中间件如果注册太早,$request->rule()->getName() 会返回空或反射路径(如 '\app\controller\Admin\UserController@list'),根本拿不到真实路由名,导致权限比对永远失败。它必须在路由解析完成、控制器尚未执行的阶段介入。
正确做法是把中间件加到 app/middleware.php 的 'http' 数组靠后位置,例如放在 SessionInit 和 AllowCrossDomain 之后,但不能在 CheckAuth 这类已有鉴权中间件之后重复叠加:
- 确保中间件类中调用
$request->rule()->getName()能稳定输出类似'admin.user.list'的字符串 - 若返回为空,检查路由是否显式命名:比如
Route::get('admin/user/list', 'admin.UserController@list')->name('admin.user.list') - 别依赖
$request->url()或拼接$request->controller() . '.' . $request->action(),大小写和命名风格易出错
权限校验必须走「用户→角色→权限」三级链路
直接查 user_permission 关联表或把权限塞进用户 JSON 字段,会导致角色变更不生效、无法审计、索引失效。RBAC 的语义核心是“角色继承”,校验依据只能是当前用户激活角色所关联的全部 auth_rule.rule_name。
中间件里应按顺序查:
- 先根据
$uid查auth_group_access表得role_id列表 - 再用这些
role_id查auth_role_rule得rule_id集合 - 最后联查
auth_rule表,提取rule_name字符串数组(如['admin.user.list', 'admin.user.delete']) - 缓存这组数据,key 建议为
'auth_rules_by_user_' . $uid,过期时间设为 30 分钟
注意:不要缓存全量权限再做 in_array,而应缓存每个用户专属的白名单——否则 A 用户删了权限,B 用户的缓存未刷新,就会误放行。
游客、超管必须短路处理,且顺序不能错
中间件最开头就要判断两类特殊身份,否则后续所有查询和缓存读取都是浪费:
- 游客(未登录):检查
Auth::id()或session('user_id')是否存在,不存在则跳转登录页或返回 JSON 错误 - 超级管理员:查用户表
is_super = 1字段,命中即return $next($request)放行,**绝不能放在这段逻辑之后** - 超管跳过权限检查,但不能跳过登录态验证——先确认是合法登录用户,再判是否为超管
常见错误是把超管判断写在缓存读取之后,结果每次请求都触发 DB 查询或 Redis 读取,性能白白损耗。
接口与页面请求要区分响应格式
同一个中间件拦截 GET /admin/user/123 页面请求和 DELETE /api/v1/user/123 AJAX 请求,但前端需要完全不同的反馈方式:
- 页面请求(非 AJAX):重定向到 403 模板页或后台首页
- AJAX 请求:返回标准 JSON:
['code'=>403, 'msg'=>'无操作权限'],状态码设为 403 - 判断依据用
$request->isAjax()+$request->header('accept') === 'application/json'双保险,避免某些前端框架漏传X-Requested-With
别让前端卡在控制台看不到错误,也别让页面跳转时把 403 当成普通 HTML 渲染——这两类响应必须在中间件里明确分支处理。
权限校验不是“写了中间件就完事”,关键在于每一步数据来源是否可信、缓存 key 是否带用户上下文、短路逻辑是否前置。最容易被忽略的是:路由名没对齐、超管判断放错位置、AJAX 响应没适配,这三处一错,整个 RBAC 就形同虚设。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











