除了 `RBAC`(基于角色的访问控制)之外,`Yii2` 还支持 `ACL`(访问控制列表)权限管理。`ACL` 是一种基于资源的权限管理方式,可以为每个资源指定不同的权限控制规则。下面是一个简单的 ACL 权限管理配置示例: ### 1. 定义资源和规则 在你的应用程序中,你需要定义资源和规则。资源是一个具体的对象,可以是一个模型、一个控制器或者一个操作。规则描述了谁可以执行哪些操作。 ```php class Post extends \yii\db\ActiveRecord { // ... public function getAcl() { return [ 'view' => [ 'type' => Acl::TYPE_ALLOW, 'roles' => ['admin', 'author'], ], 'create' => [ 'type' => Acl::TYPE_ALLOW, 'roles' => ['admin'], ], 'update' => [ 'type' => Acl::TYPE_ALLOW, 'roles' => ['admin'], 'bizRule' => function($user, $post) { return $user->id === $post->created_by; }, ], 'delete' => [ 'type' => Acl::TYPE_ALLOW, 'roles' => ['admin'], ], ]; } } ``` 在上面的代码中,我们为` Post` 模型定义了四个资源:`view`、`create`、`update` 和 `delete`。每个资源都有一个 `type` 属性,指定了是允许还是拒绝访问。`roles` 属性指定了哪些角色可以访问该资源。`bizRule `属性是一个回调函数,用于自定义访问控制规则。在 `update` 资源中,我们使用了一个回调函数,如果当前用户是该文章的创建者,则允许访问。 ### 2. 实现 ACL 权限管理 在你的应用程序中,你需要实现 `ACL` 权限管理。你可以在控制器中使用行为(`Behavior`)来实现 `ACL` 权限管理。 ```php class AclBehavior extends Behavior { public function events() { return [ Controller::EVENT_BEFORE_ACTION => 'beforeAction', ]; } public function beforeAction($event) { $action = $event->action->id; $controller = $event->action->controller->id; $route = "$controller/$action"; $modelClass = $this->owner->modelClass; $model = new $modelClass; if (isset($model->acl[$route])) { $acl = $model->acl[$route]; if ($acl['type'] === Acl::TYPE_ALLOW) { if (empty($acl['roles'])) { return true; } else { foreach ($acl['roles'] as $role) { if (Yii::$app->user->can($role)) { return true; } } } } throw new ForbiddenHttpException('You are not allowed to perform this action.'); } return true; } } ``` 在上面的代码中,我们实现了一个名为 `AclBehavior` 的行为。该行为监听了控制器的 `beforeAction` 事件,并在该事件发生时进行 `ACL` 权限检查。如果用户没有权限执行当前路由,则抛出一个 `ForbiddenHttpException` 异常。 在 `beforeAction` 方法中,我们首先获取当前路由,并创建相应的模型实例。然后,我们检查该模型的 ACL 配置,如果存在相应的规则,则根据规则进行权限检查。如果用户拥有相应的角色,则允许访问;否则,抛出异常。 将 ACL 行为应用到控制器 在需要应用 ACL 权限管理的控制器中,添加以下代码: ```php use common\components\AclBehavior; class PostController extends Controller { public function behaviors() { return [ AclBehavior::className(), ]; } // ... } ``` 在上面的代码中,我们将 `AclBehavior` 行为添加到` PostController `控制器中。这样,在 `PostController` 控制器中的每个动作之前,都会执行` AclBehavior` 行为中的权限检查逻辑。 通过以上步骤,我们可以在控制器中实现 `ACL` 权限管理,并在 `AclBehavior` 行为中统一管理权限检查逻辑。在模型中定义资源和规则,可以使 ACL 配置更加灵活和可维护。