yiisoft/rbac

Yii 基于角色的访问控制

2.0.0 2024-03-07 09:55 UTC

README

Yii

Yii 基于角色的访问控制


Latest Stable Version Total Downloads Build status codecov Mutation testing badge static analysis type-coverage

此包提供了RBAC(基于角色的访问控制)库。它用于Yii 框架,但也可用作独立组件。

功能

  • 灵活的 RBAC 层次结构,包括角色、权限和规则。
  • 角色继承。
  • 检查访问时可以将数据传递给规则。
  • 多种存储适配器。
  • 可以使用不同的存储来处理用户-角色分配和角色层次结构。
  • 管理 RBAC 层次的 API。

要求

  • PHP 8.1 或更高版本。

安装

可以使用 Composer 安装此包。

composer require yiisoft/rbac

以下存储之一也可以安装:

此外,还有一个规则工厂实现 - Rules Container(基于 Yii Factory)。

所有这些都可以用自定义实现替换。

通用用法

设置管理器

使用 RBAC 的第一步是配置一个 Manager 实例。

use Yiisoft\Rbac\AssignmentsStorageInterface;
use Yiisoft\Rbac\ItemsStorageInterface;
use Yiisoft\Rbac\RuleFactoryInterface;

/**
* @var ItemsStorageInterface $itemsStorage
* @var AssignmentsStorageInterface $assignmentsStorage
* @var RuleFactoryInterface $ruleFactory
*/
$manager = new Manager($itemsStorage, $assignmentsStorage, $ruleFactory);

它需要以下依赖项

  • 项目存储(层次结构本身)。
  • 分配存储,其中用户 ID 映射到角色。
  • 规则工厂。通过给定的名称创建一个规则实例。

虽然存储是必需的,但规则工厂是可选的,省略时将使用 SimpleRuleFactory。对于更高级的用法,例如通过别名解析规则和在规则构造函数中传递参数,可以额外安装 Rules Container 或编写自己的实现。

选择存储后端的几个提示

  • 角色和权限通常可以被认为是“半静态”的,因为它们仅在更新应用程序代码时更改,因此可能适合使用 PHP 存储。
  • 另一方面,分配可能是“动态”的。它们更改得更频繁:当创建新用户或从应用程序内部更新用户角色时。因此,可能适合使用数据库存储进行分配。

管理 RBAC 层次

在能够检查权限之前,必须定义 RBAC 层次。通常是通过控制台命令或迁移来完成的。层次结构由权限、角色和规则组成

  • 权限是访问粒度,例如“创建帖子”或“阅读帖子”。
  • 角色是分配给用户的。角色被授予一个或多个权限。典型的角色是“经理”或“管理员”。
  • 规则是具有某些数据的 PHP 类,它回答单个问题“给定数据,用户是否有请求的权限”。

要创建权限,请使用以下代码

use Yiisoft\Rbac\ManagerInterface;
use Yiisoft\Rbac\Permission;

/** @var ManagerInterface $manager */
$manager->addPermission(new Permission('createPost'));
$manager->addPermission(new Permission('readPost'));
$manager->addPermission(new Permission('deletePost'));

添加一些角色

use Yiisoft\Rbac\ManagerInterface;
use Yiisoft\Rbac\Role;

/** @var ManagerInterface $manager */
$manager->addRole(new Role('author'));
$manager->addRole(new Role('reader'));

接下来,我们需要将权限附加到角色上

use Yiisoft\Rbac\ManagerInterface;

/** @var ManagerInterface $manager */
$manager->addChild('reader', 'readPost');
$manager->addChild('author', 'createPost');
$manager->addChild('author', 'deletePost');
$manager->addChild('author', 'reader');

上述示例的层次结构

有时,基本权限不足以满足需求。在这种情况下,规则很有帮助。规则是可以添加到权限和角色中的PHP类

use Yiisoft\Rbac\Item;
use Yiisoft\Rbac\RuleContext;
use Yiisoft\Rbac\RuleInterface;

class ActionRule implements RuleInterface
{
    public function execute(?string $userId, Item $item, RuleContext $context): bool;
    {
        return $context->getParameterValue('action') === 'home';
    }
}

添加规则后,只有在规则的方法 execute() 返回 true 时,才会考虑角色或权限。

参数如下

  • $userId 是要检查权限的用户ID;
  • $item 是规则附加到的RBAC层次结构项;
  • $context 是提供访问参数的规则上下文。

要使用Manager与规则,请指定它们的名称,并将其添加到权限或角色中

use Yiisoft\Rbac\ManagerInterface;
use Yiisoft\Rbac\Permission;

/** @var ManagerInterface $manager */
$manager->addPermission( 
    (new Permission('viewList'))->withRuleName(ActionRule::class),
);

// or

$manager->addRole(
    (new Role('NewYearMaintainer'))->withRuleName(NewYearOnlyRule::class)
);

规则名称action_rulenew_year_only_rule将通过规则工厂分别解析为ActionRuleNewYearOnlyRule类的实例。

如果您需要一次性聚合多个规则,请使用组合规则

use Yiisoft\Rbac\CompositeRule;

// Fresh and owned
$compositeRule = new CompositeRule(CompositeRule::AND, [FreshRule::class, OwnedRule::class]);

// Fresh or owned
$compositeRule = new CompositeRule(CompositeRule::OR, [FreshRule::class, OwnedRule::class]);

分配角色给用户

要为具有给定ID的用户分配特定角色,请使用以下代码

use Yiisoft\Rbac\ManagerInterface;

/** @var ManagerInterface $manager */
$userId = 100;
$manager->assign('author', $userId);

这可以在管理面板中完成,通过控制台命令,或者它可以构建到应用程序的业务逻辑中。

检查权限

要检查权限,请获取Yiisoft\Access\AccessCheckerInterface的实例并使用它

use Psr\Http\Message\ResponseInterface; 
use Yiisoft\Access\AccessCheckerInterface;

public function actionCreate(AccessCheckerInterface $accessChecker): ResponseInterface
{
    $userId = getUserId();

    if ($accessChecker->userHasPermission($userId, 'createPost')) {
        // author has permission to create post
    }
}

有时您需要添加仅限访客的权限,该权限未分配给任何用户ID。在这种情况下,您可以指定一个分配给访客用户的角色

use Yiisoft\Access\AccessCheckerInterface;
use Yiisoft\Rbac\Permission;
use Yiisoft\Rbac\Role;

/** 
 * @var ManagerInterface $manager
 * @var AccessCheckerInterface $accessChecker 
 */
$manager->setGuestRoleName('guest');
$manager->addPermission(new Permission('signup'));
$manager->addRole(new Role('guest'));
$manager->addChild('guest', 'signup');

$guestId = null;
if ($accessChecker->userHasPermission($guestId, 'signup')) {
    // Guest has "signup" permission.
}

如果涉及到规则,您可能需要传递额外的参数

use Yiisoft\Rbac\ManagerInterface;

/** @var ManagerInterface $manager */
$anotherUserId = 103;
if (!$manager->userHasPermission($anotherUserId, 'viewList', ['action' => 'home'])) {
    echo 'reader hasn\'t "index" permission';
}

文档

如果您需要帮助或有任何问题,请访问Yii 论坛,那里是一个很好的地方。您还可以查看其他Yii 社区资源

许可证

Yii 基于角色的访问控制是免费软件。它根据BSD许可证的条款发布。有关更多信息,请参阅LICENSE

Yii 软件维护。

支持项目

Open Collective

关注更新

Official website Twitter Telegram Facebook Slack