auth::check()不是开箱即用函数,必须显式调用auth::setuser($uid)注册用户、权限名与路由定义严格一致、中间件在session初始化后且早于控制器执行。

Auth::check() 在 ThinkPHP 后台权限控制中不是“开箱即用”的魔法函数,它依赖三件事:用户已通过 Auth::setUser($uid) 显式注册、权限规则名与路由定义完全一致、中间件执行时机早于控制器但晚于 Session 初始化。
Auth::check() 总是返回 false 的真实原因
不是权限没配对,而是 Auth 实例根本没拿到用户上下文。TP6 默认从 session('think_auth') 读缓存,但登录成功后没人调 Auth::setUser($uid),缓存就为空。
- 登录逻辑里必须紧接在验证通过后立即执行
Auth::setUser($uid),不能等重定向之后 - 中间件中别用
$request->param('id')拼权限名,应统一用路由规则字符串(如admin/user/edit) - 多应用模式下(比如
admin和api分开),Auth::check()必须传第三个参数指定 app 名,否则查的是默认app下的规则
权限名必须和 route/app.php 定义严格匹配
权限名不是前端按钮文案,也不是方法名,它是路由绑定时声明的完整路径标识。错一个字符、斜杠/点号混用、大小写不一致,Auth::check() 就失效。
- 若路由定义为
Route::get('admin/user/list', 'admin.UserController@list');,权限名只能是admin/user/list - 不能写成
admin.user.list、user_list或Admin/User/List - 菜单渲染时,按钮权限也得按这个规则来,比如删除按钮对应
admin/user/delete,而不是user:delete
auth_rule 表字段冗余导致性能崩塌
很多人一建表就给 auth_rule 加 status、sort、remark,结果后期 JOIN 查询越来越慢——因为 TP 的 Auth 类只认 name 和 type,其余字段纯属干扰。
-
condition字段慎用:每次鉴权都会拼 SQL 执行,极易引发全表扫描或 SQL 注入,非动态权限场景一律留空 -
pid必须是INT类型且允许为0,否则递归生成菜单时会无限循环 - 角色-用户关系必须走
auth_group_access表,字段名必须是uid和group_id,自定义成user_id或role_id会导致Auth类完全忽略分配关系
中间件里权限拦截不生效的典型写法
直接在中间件 handle 方法里写 if (!Auth::check(...)) { return redirect(...) } 是常见错误。TP6 中间件执行时,Auth 实例尚未加载用户 ID,Auth::id() 返回 null,Auth::check() 必然失败。
- 确保中间件注册在
app/middleware.php的'http'数组中,且位置在SessionInit之后 - 改用
Auth::getUser()判断是否为 null,再决定是否继续鉴权 - 更稳妥的做法:先确认用户已登录(查 session 或 token),再调
Auth::check(),不要把两件事耦合在一个判断里
真正麻烦的从来不是写几行权限代码,而是不同登录态(Session / JWT / Cookie)共存时,Auth 类内部的用户来源识别、缓存键生成、过期策略全部要手动对齐——稍有偏差,就会出现“明明分配了权限却提示无权访问”这种静默故障。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











