Auth::check()失败的根本原因是权限未正确加载到缓存或时机错误:登录后须立即调用Auth::setUser($uid),权限名须严格匹配路由规则,多应用需指定app名,type必须为2(按钮/API),且变更权限后须清理缓存并检查关联表残留。

权限校验失败、按钮不可见、403却不报错——这些问题不是配置漏了,而是 Auth::check() 没在正确时机被调用,或权限标识根本没进缓存。
中间件里 Auth::check() 总返回 false?先看 Auth::setUser() 调了没
ThinkPHP8 的 Auth 类默认从 session 或缓存读权限列表,而不是实时查库。如果登录后没主动调用 Auth::setUser($uid),后续所有 Auth::check('admin/user/edit') 都会返回 false,哪怕数据库里角色和权限全对。
- 登录成功后必须立刻执行
Auth::setUser($user['id']),不能等到跳转完成或中间件里再查 - 中间件中别传
$request->param('id')拼权限名,应统一用路由规则名(如admin/user/delete),否则 URL 改参数就失效 - 多应用模式下(如
admin和api分开),Auth::check()必须显式传入 app 名:Auth::check('user/delete', $uid, 'admin') - 若用 JWT 或无状态认证,需改用 Redis 缓存权限:键为
user_permissions_{$uid},值为字符串数组,过期设为 3600 秒
权限标识 name 必须和路由定义完全一致
权限名不是“看着像就行”,它必须严格匹配 route/app.php 中注册的完整路由规则名,包括斜杠分隔、大小写、前后缀。
- 写了
Route::get('admin/user/list', 'admin.UserController@list'),权限名只能是admin/user/list -
admin.user.list、user_list、/admin/user/list(开头多斜杠)都会导致Auth::check()失败 - 按钮级权限也一样:删除按钮对应接口是
admin/user/delete/:id,权限名就得是admin/user/delete,不带:id - 前端菜单渲染时,建议用
request()->rule()->getName()动态取当前路由名,避免硬编码出错
为什么 getAllPermissions() 每次都查库?别在模型里写这个方法
在 User 模型里写个 getAllPermissions() 方法,看似封装干净,实际每次请求都触发 N+1 查询:查角色 → 查每个角色的权限 → 合并去重。高并发下 DB 连接池直接打满。
立即学习“PHP免费学习笔记(深入)”;
- 登录后一次性查出该用户全部权限名(通过
role_permission+permissionsJOIN),存入Session或Redis - 中间件中优先读
session('user_permissions'),为空才 fallback 到数据库,并立即回填 - 权限变更(后台改角色/删权限)时,必须主动清除缓存:
cache('user_permissions_'.$uid, null),否则脏数据持续存在 - 别依赖
Cache::tag('auth')自动清理——RBAC 场景 tag 粒度太粗,容易误删其他业务缓存
按钮没权限但页面能打开?检查权限表的 type 字段和 condition 字段
菜单能显示、接口能进、但按钮点不动,大概率是权限表中 type 或 condition 字段干扰了判定逻辑。
-
auth_rule表中type = 1表示菜单,type = 2表示操作(按钮/API),Auth::check()默认只认type = 2的记录;按钮权限必须设为type = 2 -
condition字段慎用:它会在每次鉴权时拼 SQL 执行,极易引发 SQL 注入或全表扫描;除非真需要动态条件(如“仅允许编辑自己创建的内容”),否则留空 - 常见错误:把按钮权限误设为
type = 1(菜单),或给condition填了status=1却忘了加索引,导致查询超时后自动返回 false - 调试时可临时在中间件里 dump
Db::name('auth_rule')->where('name', 'admin/user/delete')->find()确认字段值
最易被忽略的一点:权限变更后,不只是清缓存,还要确认 role_permission 关联表里有没有残留旧权限 ID —— 数据库外键没设 ON DELETE CASCADE 时,删权限不删关联,就会出现“界面上删了权限,用户还能点”的现象。



















