ThinkPHP 6 不内置基于策略的授权(如 ABAC 或 Laravel Gate),必须手动构建策略评估层;RBAC 是静态角色-权限映射,策略授权则动态判断主体对特定资源执行操作是否允许,并需考虑环境条件。

ThinkPHP 6 本身不内置基于策略的授权(如 ABAC 或类似 Laravel Gate 的策略机制),要实现「基于策略的授权」,必须手动构建策略评估层,不能依赖 Auth 组件或中间件直接提供。
明确策略授权和 RBAC 的区别
RBAC 是“用户 → 角色 → 权限节点(路由名)”的静态映射;而策略授权是动态判断:当前主体(用户)能否对某个资源(如一条订单)执行某个操作(如编辑、删除),还要考虑环境条件(如时间、IP、状态)。ThinkPHP 没有 Policy 类、Gate::define() 或自动注入策略的机制。
手动实现策略评估器(AbacEvaluator)
你需要自己写一个策略评估类,通常放在 app/service/ 或 app/policy/ 下:
- 定义接口或基类,统一接收
$user、$resource、$action、$context四个参数 - 策略规则可存数据库(如
policy_rules表),字段包括:name(如 'order.update.own')、expression(PHP 表达式或 JSON 规则)、status - 在运行时解析表达式,例如:
$user->id === $resource->user_id && $resource->status === 'draft' - 避免
eval(),推荐用轻量表达式引擎(如symfony/expression-language)或预编译逻辑分支
在控制器中调用策略判断
不要在中间件里做策略校验(太早,资源未加载);应在具体操作前检查:
立即学习“PHP免费学习笔记(深入)”;
- 先查出目标资源:
$order = Order::find($id) - 再调用策略服务:
if (! app(PolicyService::class)->check($user, $order, 'update')) { abort(403); } - 可封装为模型方法,例如
$order->canUpdate($user),把策略逻辑下沉到模型或策略类中
结合路由与权限中间件做分层控制
策略授权不是替代 RBAC,而是补充:
- 中间件负责第一道关:用户是否能访问「订单编辑页」这个路由(RBAC 判断)
- 控制器内负责第二道关:用户能否编辑「这条特定订单」(策略判断)
- 这样既保证入口安全,又守住数据边界,避免越权读写



















