首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii2 RBAC 權限管理實戰:DbManager 角色/權限 CRUD、分配、檢查完整程式碼

     編輯:PHP 相關知識

Yii2 RBAC 權限管理實戰:DbManager 角色/權限 CRUD、分配、檢查完整程式碼

Yii2 DbManager 將 RBAC 資料存儲於資料庫四張表(auth_item, auth_item_child, auth_assignment, auth_rule)。本文提供完整後台管理實作:遷移建表、Model 區分角色/權限、Controller CRUD、角色-權限關聯、用戶-角色指派、權限檢查中介層。

1. 執行遷移建表

# 終端機執行
yii migrate --migrationPath=@yii/rbac/migrations/

生成四表:auth_item (角色+權限), auth_item_child (繼承), auth_assignment (用戶指派), auth_rule (規則)。

2. Model 區分角色與權限

<?php
// models/RoleForm.php
namespace app\models;
use Yii;
use yii\rbac\Item;

class RoleForm extends \app\models\AuthItem {
    public function init() {
        parent::init();
        $this->type = Item::TYPE_ROLE; // 常數 1
    }
}

// models/PermissionForm.php
namespace app\models;
use Yii;
use yii\rbac\Item;

class PermissionForm extends \app\models\AuthItem {
    public function init() {
        parent::init();
        $this->type = Item::TYPE_PERMISSION; // 常數 2
    }
}

// models/AuthItem.php (GII 生成後新增屬性)
namespace app\models;
use Yii;

class AuthItem extends \yii\db\ActiveRecord {
    public $child = []; // 用於角色編輯時接收權限陣列
    // ... 其他屬性與規則
}
?>

3. 權限 Controller CRUD

<?php
namespace app\controllers;
use Yii;
use yii\rbac\Permission;
use app\models\PermissionForm;

class PermissionController extends \yii\web\Controller {
    public function actionCreate() {
        $model = new PermissionForm();
        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $perm = new Permission();
            $perm->name = $model->name;
            $perm->description = $model->description;
            $perm->ruleName = $model->ruleName;
            $perm->data = $model->data;
            Yii::$app->authManager->add($perm);
            return $this->redirect(['index']);
        }
        return $this->render('create', ['model' => $model]);
    }

    public function actionUpdate($name) {
        $model = $this->findModel($name);
        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $perm = new Permission();
            $perm->name = $model->name;
            $perm->description = $model->description;
            $perm->ruleName = $model->ruleName;
            $perm->data = $model->data;
            Yii::$app->authManager->update($name, $perm);
            return $this->redirect(['index']);
        }
        return $this->render('update', ['model' => $model]);
    }

    public function actionDelete($name) {
        $perm = Yii::$app->authManager->getPermission($name);
        if ($perm) Yii::$app->authManager->remove($perm);
        return $this->redirect(['index']);
    }

    protected function findModel($name) {
        $perm = Yii::$app->authManager->getPermission($name);
        if (!$perm) throw new \yii\web\NotFoundHttpException();
        $model = new PermissionForm();
        $model->name = $perm->name;
        $model->description = $perm->description;
        $model->ruleName = $perm->ruleName;
        $model->data = $perm->data;
        return $model;
    }
}
?>

4. 角色 Controller CRUD + 權限關聯

<?php
namespace app\controllers;
use Yii;
use yii\rbac\Role;
use app\models\RoleForm;

class RoleController extends \yii\web\Controller {
    public function actionCreate() {
        $model = new RoleForm();
        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $role = new Role();
            $role->name = $model->name;
            $role->description = $model->description;
            Yii::$app->authManager->add($role);
            return $this->redirect(['index']);
        }
        $model->child = $this->getRolePermissions($model->name);
        $permissions = Yii::$app->authManager->getPermissions();
        return $this->render('create', ['model' => $model, 'permissions' => $permissions]);
    }

    public function actionUpdate($name) {
        $model = $this->findModel($name);
        $oldPermissions = $this->getRolePermissions($name);

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $newPermissions = Yii::$app->request->post('AuthItem')['child'] ?? [];
            if (empty($newPermissions)) {
                Yii::$app->session->setFlash('error', '角色至少需要一個權限');
                return $this->refresh();
            }

            // 先移除舊關聯
            if (!empty($oldPermissions)) {
                Yii::$app->authManager->removeChildren($model);
            }

            // 建立新關聯
            $role = Yii::$app->authManager->getRole($name);
            foreach ($newPermissions as $permName) {
                $perm = Yii::$app->authManager->getPermission($permName);
                if ($perm) Yii::$app->authManager->addChild($role, $perm);
            }
            return $this->redirect(['index']);
        }

        $model->child = $oldPermissions;
        $permissions = Yii::$app->authManager->getPermissions();
        return $this->render('update', ['model' => $model, 'permissions' => $permissions]);
    }

    public function actionDelete($name) {
        $role = Yii::$app->authManager->getRole($name);
        if ($role) {
            // 遞歸移除子權限
            $children = Yii::$app->authManager->getChildren($role);
            foreach ($children as $child) {
                $perm = Yii::$app->authManager->getPermission($child->name);
                if ($perm) Yii::$app->authManager->removeChild($role, $perm);
            }
            Yii::$app->authManager->remove($role);
        }
        return $this->redirect(['index']);
    }

    private function getRolePermissions(string $roleName): array {
        $role = Yii::$app->authManager->getRole($roleName);
        if (!$role) return [];
        $children = Yii::$app->authManager->getChildren($role);
        return array_column($children, 'name');
    }

    protected function findModel($name) {
        $role = Yii::$app->authManager->getRole($name);
        if (!$role) throw new \yii\web\NotFoundHttpException();
        $model = new RoleForm();
        $model->name = $role->name;
        $model->description = $role->description;
        return $model;
    }
}
?>

5. 用戶-角色指派

<?php
// 例如在 UserController::actionAssignRole()
$roleName = Yii::$app->request->post('role');
$userId = Yii::$app->request->post('user_id');

$role = Yii::$app->authManager->getRole($roleName);
if ($role) {
    // 移除舊角色(單角色系統)
    Yii::$app->authManager->revokeAll($userId);
    // 指派新角色
    Yii::$app->authManager->assign($role, $userId);
    Yii::$app->session->setFlash('success', '角色指派成功');
}
?>

6. 權限檢查(控制器基類/Filter/Behavior)

<?php
// 基底控制器
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;

class BaseController extends Controller {
    public function behaviors() {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'allow' => true,
                        'roles' => ['@'], // 登入用戶
                        'matchCallback' => function ($rule, $action) {
                            $perm = $action->uniqueId; // 如 'user/index'
                            return Yii::$app->user->can($perm);
                        }
                    ],
                ],
            ],
        ];
    }
}
?>

或直接在動作中:if (!Yii::$app->user->can('order/create')) throw new ForbiddenHttpException();

關鍵 API 速查表

操作方法
建立角色`$auth->add(new Role(['name'=>'admin']))`
建立權限`$auth->add(new Permission(['name'=>'user/create']))`
角色授權權限`$auth->addChild($role, $permission)`
移除角色權限`$auth->removeChild($role, $permission)` / `removeChildren($role)`
用戶指派角色`$auth->assign($role, $userId)`
撤銷用戶角色`$auth->revoke($role, $userId)` / `revokeAll($userId)`
檢查權限`Yii::$app->user->can('permissionName')` 或 `$auth->checkAccess($userId, 'perm')`
獲取用戶所有權限`$auth->getPermissionsByUser($userId)`
獲取角色所有權限`$auth->getChildren($role)`

延伸閱讀

更多 Yii2 RBAC 進階:Rule 類實作業務規則(如擁有者才能編輯)、多租戶權限隔離、權限快取優化、API 權限範圍控制、動態菜單渲染、審計日誌整合、Casbin 整合替代方案,請參考本站專題系列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved