本文章地址:https://wutong.me/2018/02/01/yii2-rbac-step.html 转载请注明出处

Yii2中的RBAC 还是比较快捷方便的,支持 PHP、数据库等方式存储权限配置。

检查方式

\Yii::$app->authManager->checkAccess(用户id,权限名称,提供给Rule的参数);
//或
\Yii::$app->user->can(权限名称,提供给Rule的参数);

返回值为 bool 类型,true 为有这个权限,false为没有这个权限

checkAccess 检查流程

public function checkAccess($userId, $permissionName, $params = [])
{
    $assignments = $this->getAssignments($userId);
 
    if ($this->hasNoAssignments($assignments)) {
        return false;
    }

    return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments);
}

第一步,会调用AuthManager::getAssignments 方法获得该用户所绑定的角色、权限等信息。

第二步,检查此用户的角色权限是否为空有没有初始化默认角色,如果都没有的话则返回false并终止权限判断。

第三步,递归的调用 AuthManager::checkAccessRecursive 方法来检查有没有此权限。

checkAccessRecursive 检查流程

protected function checkAccessRecursive($user, $itemName, $params, $assignments)
{
    if (!isset($this->items[$itemName])) {
        return false;
    }

    /* @var $item Item */
    $item = $this->items[$itemName];
    Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission : $itemName", __METHOD__);

    if (!$this->executeRule($user, $item, $params)) {
        return false;
    }

    if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) {
        return true;
    }

    foreach ($this->children as $parentName => $children) {
        if (isset($children[$itemName]) && $this->checkAccessRecursive($user, $parentName, $params, $assignments)) {
            return true;
        }
    }

    return false;
}

第一步,判断当前 AuthManger 实例中的 items 属性中是否存在这个权限,items 中保存了所有创建的角色、权限,如果没有的话则直接返回 false 并结束。

第二步,如果有这个权限的话,则判断这个权限是否绑定了 Rule 实例(通过的权限的ruleName属性值是否为null来判断),如果绑定了Rule则执行Rule实例的execute方法,然后根据execute方法的返回值觉得是否终止检查。

第三步,判断用户的当前的$assignments中是否存在这个权限 或者 当前默认所有角色中是否存在这个权限,满足其中一种的话则返回true,注意:如果权限实际是角色的话才有意义,因为判断代码为 in_array($itemName, $this->defaultRoles)

第四步,循环检查AuthManager::children属性里面每个项的value数组中是否包含了要验证的权限并且递归调用checkAccessRecursive检查当前用户是否有这个项的key对应的权限,如两者都满足的话则返回true并终止判断。