权限判断逻辑应放在中间件而非控制器,用authmiddleware封装并注入authservice;数据库需拆分角色、权限项、授权规则三层结构;避免直接使用think\auth类,应继承重写以支持动态缓存与行级校验;路由元数据标记实现兼容性降级。

权限判断逻辑该放在哪里?别在控制器里硬写 if
动态权限控制的核心不是“能不能进”,而是“谁在什么上下文下能做什么”。把 checkPermission() 塞进每个控制器方法里,等于把路由、业务、鉴权全搅在一起——改个菜单就得翻十来个文件。
ThinkPHP 的中间件(app/middleware.php 或类中间件)才是合理位置。它天然拦截请求,在进入控制器前完成权限裁决,还能统一处理拒绝响应(比如重定向到 403 页面或返回 JSON 错误)。
- 用
AuthMiddleware类封装权限检查,构造函数注入AuthService,避免直接操作数据库 - 不要在中间件里调
$this->request->action()判断动作名——ThinkPHP 的Route::rule()可能映射了别名,真实操作名和路由定义不一致 - 推荐用
$this->auth->can($routeName, $resourceId)这种语义化接口,而不是传一堆字符串拼权限码
数据库表结构怎么设计才不卡死后期扩展?
常见错误是只建一张 user_role 和一张 role_permission,然后靠 permission_code 字段存 "post:edit" 这类字符串。问题来了:要支持「编辑自己发布的文章」这种行级权限时,字段就扛不住了。
必须拆三层:角色(role)、权限项(permission)、授权规则(auth_rule)。其中 auth_rule 表要包含 rule_type(如 global/own/dept)、scope_field(如 user_id)、scope_value(可为空,表示动态取值)。
-
permission表的name字段建议用点号分隔,如"article.edit",方便按模块前缀批量查 - 避免在
auth_rule中存 SQL 片段——执行时无法预编译,也难审计。把条件逻辑收进AuthService::evaluateRule()方法里更可控 - 加索引:组合索引
(role_id, permission_id, rule_type)能显著加快鉴权查询
think\Auth 类能不能直接用?小心它的缓存陷阱
ThinkPHP 自带的 think\Auth 类确实提供 check() 方法,但它默认基于静态数组缓存权限,且不感知用户角色变更。用户刚被分配新角色,刷新页面还是没权限——因为缓存没清,也没钩子让你插。
真正可用的方式是继承并重写:class DbAuth extends \think\Auth,把 _getAccessList() 改成查数据库,并在用户登录、角色变更后主动删掉 cache('auth_'.$uid)。
- 别依赖
Auth::init()的配置自动加载——它读的是配置文件里的固定规则,和数据库驱动冲突 - 在
DbAuth::check()里补上资源 ID 的校验逻辑,例如article.edit.123中的123需要查出该文章的作者再比对 - 开启 Redis 缓存时,key 必须带上用户 ID 和时间戳(如
auth:u123:t1712345678),否则并发修改角色会导致脏读
如何让权限开关不影响已有接口的兼容性?
上线后突然加权限,老接口如果没做降级处理,前端一调就 403,运营同学马上打电话。关键不是“拦住”,而是“知道拦谁、为什么拦、怎么绕过”。
最稳妥的做法是在路由定义里加元数据标记,比如 ['auth' => ['required' => true, 'fallback' => 'guest_read']],然后在中间件里解析这个配置,决定是抛异常、返回空数据,还是走游客权限流。
- 给所有受控接口加
X-Auth-Debug响应头,内容为rule=article.edit.456|hit=yes|source=db,方便前端或测试快速定位问题 - 禁止用
try/catch捕获权限异常后静默吞掉——至少记一条 warning 日志,含$request->url()和$auth->getLastRule() - 灰度期间可按用户 UID 尾号放行,比如
uid % 100 的用户走旧逻辑,其余走新鉴权,而不是一刀切
权限模型越往后越容易陷入「规则嵌套规则」的泥潭。一开始就想支持所有场景,最后连自己都解释不清某条数据为什么能被访问——先跑通「角色→权限→资源」主链路,再按需加行级、字段级、时间窗等约束,比堆配置强得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










