thinkphp权限控制需手动串联登录、缓存、路由、中间件和数据库;90%“没权限”问题源于未配中间件、未调auth::setuser()、未清理缓存;auth::check()返回false主因是环境未就位,如未设用户id或权限标识不匹配。

ThinkPHP 权限控制不是开箱即用的“开关”,而是必须手动串联登录、缓存、路由、中间件和数据库的完整链路。不配中间件、不调 Auth::setUser()、不清理缓存,90% 的“没权限”问题都卡在这三步。
Auth::check() 总返回 false 怎么办
这不是函数坏了,是运行环境没就位。
-
Auth::check()默认从 session 读用户 ID 和权限缓存,但登录后你没调Auth::setUser($uid),它就查不到任何数据 - 第二个参数必须是用户 ID(整型),不能传数组或字符串 ID;多角色场景下得自己拼权限列表,
Auth::check()不支持自动合并角色权限 - 权限标识
$node必须和auth_rule.name字段**逐字符一致**:大小写、斜杠方向、末尾是否带斜杠(admin/user/edit≠admin/user/edit/) - TP6.1+ 已移除
condition字段的eval()支持,如果表里还留着 PHP 表达式,会直接报ParseError
rbac 中间件为什么拦不住接口请求
因为它根本没注册到目标路由上。
- 中间件必须显式绑定到路由分组,比如在
app/middleware.php写'admin' => ['rbac'],再在路由定义里用Route::group('admin', ...)->middleware('rbac') - 别把中间件加到全局队列(
'*' => ['rbac']),TP6 的 rbac 中间件不识别未声明的路由规则,会导致白名单失效或全站 403 - 白名单路径要带完整前缀,如
'/admin/login',不能写成'login'或'admin.login';通配符(*)不被支持 - 中间件执行顺序很重要,必须放在
SessionInit之后,否则读不到 session 数据
按钮级权限怎么落地不翻车
前端 data-permission 隐藏按钮只是障眼法,后端校验才是命门。
- 权限码建议用点号分隔(如
article.delete),和路由名解耦——别依赖$this->request->action()拼,它只返回方法名,不包含控制器上下文 - 权限数据必须缓存,推荐 Redis,key 设为
'user_permissions_' . $userId;每次分配/回收权限后,立刻删掉该 key 和通用规则缓存'auth_rules_all' - 别在 Swoole/Workerman 长连接中用 static 变量缓存权限,进程间不共享,会导致部分请求误判
-
getRolePermission()返回空,先查auth_role_access是否有记录,再确认auth_rule.status = 1——哪怕一条规则 status 是 0,整个角色权限列表都会被跳过
字段级脱敏和动态条件怎么搞
AuthRule::check() 压根不处理这个层级,得换思路。
- “仅查看自己工资”这类逻辑,不能塞进
condition字段(已废弃且危险),应该在控制器里用Db::where('user_id', $this->userId)提前过滤数据 - 字段可见性要在数据组装阶段干预:查出原始数据后,用角色权限列表判断哪些字段该隐藏或脱敏,例如对
salary_real字段做isset($permissions['hr.salary.view']) ? $data['salary_real'] : '****' - 菜单、按钮、接口、字段,这四层权限必须分开建模:菜单走
type = 'menu',按钮/接口用type = 'action',字段级另建规则表或用 JSON 字段描述,混在一起后期必崩
最常被忽略的一点:权限变更后,不只是清缓存,还要确认 auth_rule.status 全是 1,且 auth_role_access 里没有残留的脏关联记录——这两处静默失效,比缓存更难排查。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











