auth::check()总不生效主因是路由名、权限表字段、中间件执行时机三者未对齐:如auth_rule.name用点号而路由为斜杠、多应用未传参数、中间件在路由匹配前执行致$request->rule()为空。

模块权限控制不是靠“加个中间件”就完事的,核心是路由名、权限表字段、中间件执行时机三者对齐。错一个,Auth::check() 就永远返回 false。
为什么 Auth::check() 总是不生效
最常见原因不是逻辑写错了,而是底层依赖没对上:
-
Auth::check()默认查的是session('think_auth')缓存,但登录后没调用Auth::setUser($uid),缓存压根没生成 - 权限表
auth_rule.name填的是admin.user.list,而路由定义实际是Route::get('admin/user/list', ...),Auth类只认斜杠分隔的admin/user/list,不认点号 - 用了多应用(如
admin和api),但Auth::check()没传第三个参数指定应用名,默认只查app应用下的规则 - 中间件注册位置太靠前,在路由还没匹配完成时就执行了,
$request->rule()为null,导致取不到路由名
中间件必须在路由匹配之后运行
ThinkPHP 的中间件执行顺序直接影响能否拿到路由信息。模块级权限校验必须等路由解析完成才能做判断:
- 中间件类里不能用
$request->url()或$request->path()去拼权限字符串——URL 路径可被重写、带参数、大小写不敏感,不可靠 - 必须用
$request->rule()->getName()获取路由规则名,它来自route/app.php中定义的完整标识(如admin/user/list) - 在
app/middleware.php的'http'数组中,该中间件要放在AllowCrossDomain之后、控制器执行之前,典型位置是倒数第二或第三位 - 如果用了
Route::group('admin', ...)->middleware(...),注意 group 绑定的中间件是前置执行,但依然能拿到已匹配的路由规则
模块权限名怎么定义才不翻车
权限名不是随便起的别名,它是数据库查询和代码校验的唯一键:
- 必须与
route/app.php中路由定义的 action 标识完全一致,包括斜杠方向、有无末尾斜杠(admin/user/list≠admin/user/list/) - 多应用下必须带前缀,比如
admin/user/list和api/v1/order/create,不能共用同一段字符串 - 不要把 HTTP 方法塞进 name 字段(如
admin/user/list|POST),应在auth_rule表单独加method字段存GET/POST - 菜单项和操作权限建议用
type字段区分:menu用于前端渲染侧边栏,permission用于后端接口校验,避免混用
游客、超管、普通用户要分三路处理
权限中间件不是“全量查表”,得短路掉明确场景,否则性能差还容易漏逻辑:
- 未登录用户(游客):直接重定向到登录页,别走任何权限查询,
if (empty($uid)) { $this->redirect('/login') } - 超级管理员(
is_super = 1):直接return $next($request)放行,不查表、不校验、不缓存穿透 - 普通用户:查
auth_group_access得角色 ID 列表 → 查role_auth得权限规则 ID 列表 → 查auth_rule得name字段 → 与当前路由名比对 - 别在中间件里手动拼 SQL 或用
whereRaw带条件查condition字段——除非真需要动态数据权限(如“只看自己创建的内容”),否则留空,防注入也防慢查询
真正卡住人的从来不是“怎么写中间件”,而是改了路由配置忘了同步更新 auth_rule.name,或是缓存没清导致新权限半天不生效。每次上线前,盯住三件事:路由定义、权限表记录、Auth::setUser() 调用时机。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











