olivier127 / rbac-bundle
Symfony PhpRabcBundle 允许在 symfony 项目中使用 RBAC 控制访问
Requires
- php: ^8.1
- doctrine/annotations: ^2.0
- doctrine/doctrine-bundle: ^2.5
- doctrine/doctrine-migrations-bundle: ^3.2
- doctrine/orm: ^3.2
- symfony/dotenv: ~6.0|~7.0
- symfony/framework-bundle: ~6.0|~7.0
- symfony/orm-pack: ^2.4
- symfony/security-bundle: ~6.0|~7.0
- symfony/twig-pack: ^1.0
- webmozart/assert: ^1.10
README
PhpRBACBundle 是一个 symfony 7 扩展包,它提供了一个完整的访问控制库,用于 PHP。它为 PHP 开发者提供了一个易于使用的库,以实现 NIST Level 2 标准分层基于角色的访问控制。它是 OWASP 为 symfony 6 制作的 phprbac.net 库的重构。
目录
如何工作?
访问 https://phprbac.net/ :) 了解权限和角色的表示以及它们之间的交互。
系统分层 RBAC 模型:蓝色:角色,灰色:用户,黄色:权限安装
只需使用 composer 包管理器安装该软件包
composer require olivier127/rbac-bundle
在 config/bundles.php 中注册该扩展包
return [ ... PhpRbacBundle\PhpRbacBundle::class => ['all' => true], ];
在 User 实体类中添加 PhpRbacBundle\Entity\UserRoleTrait 以添加 rbac 角色关系。
使用 doctrine 迁移或 doctrine 模式更新更新数据库模式以创建所有表
配置
准备 symfony
在防火墙安全配置部分的“需要预先认证的不同部分”中指定。
访问控制仅适用于网站的已认证部分。因此,我们将对所有用户使用基本的 ROLE_USER。ROLE_ADMIN 可以用于主要管理员,但他的权利将仅通过与其角色树中的 '/' 角色关联来分配。
示例
# config/packages/security.yaml security: # ... role_hierarchy: ROLE_ADMIN: ROLE_USER access_control: - { path: ^/backend, roles: ROLE_USER } - { path: ^/todolist, roles: ROLE_USER }
添加 PhpRbac 配置
您必须创建自己的实体来驱动权限和角色。
示例
/* src/Entity/Role.php */ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use PhpRbacBundle\Entity\Role as EntityRole; use PhpRbacBundle\Repository\RoleRepository; #[ORM\Entity(repositoryClass: RoleRepository::class)] #[ORM\Table('my_roles')] class Role extends EntityRole { }
/* src/Entity/Permission.php */ namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use PhpRbacBundle\Entity\Permission as EntityPermission; use PhpRbacBundle\Repository\PermissionRepository; #[ORM\Entity(repositoryClass: PermissionRepository::class)] #[ORM\Table('my_permissions')] class Permission extends EntityPermission { }
添加 php_rbac.yaml 以将实体关联到 rbac 核心
# config/packages/php_rbac.yaml php_rbac: no_authentication_section: default: deny resolve_target_entities: user: App\Entity\User role: App\Entity\Role permission: App\Entity\Permission
创建角色和权限
使用 RoleManager 和 PermissionManager 添加所有所需的角色和权限
示例
向根添加权限
/** @var PhpRbacBundle\Core\PermissionManager $manager */ $manager = $this->container->get(PermissionManager::class); $permission = $manager->add("notepad", "Notepad", PermissionManager::ROOT_ID);
添加链或权限
/** @var PhpRbacBundle\Core\PermissionManager $manager */ $manager = $this->container->get(PermissionManager::class); $manager->addPath("/notepad/todolist/read", ['notepad' => 'Notepad', 'todolist' => "Todo list", "read" => "Read Access"]);
建立 rbac 关系
添加角色的方法相同
例如,我使用了链角色 "/editor/reviewer"。审阅者是编辑的子角色,编辑是根 "/" 的子角色。
/** @var PhpRbacBundle\Core\RoleManager $manager */ $manager = $this->container->get(RoleManager::class); $manager->addPath("/editor/reviewer", ['editor' => 'Editor', 'reviewer' => "Reviewer"]);
将权限分配给角色
/** @var PhpRbacBundle\Core\RoleManager $manager */ $manager = $this->container->get(RoleManager::class); $editorId = $manager->getPathId("/editor"); $editor = $manager->getNode($editorId); $reviewerId = $manager->getPathId("/editor/reviewer"); $reviewer = $manager->getNode($reviewerId); $manager->assignPermission($editor, "/notepad"); $manager->assignPermission($reviewer, "/notepad/todolist/read"); $manager->assignPermission($reviewer, "/notepad/todolist/write");
编辑角色将拥有 /notepad 权限及其所有子权限,而审阅者角色将仅拥有 /notepad/todolist/read
和 /notepad/todolist/write
权限
分配角色给用户并检查权限
如果 UserRoleTrait
在 User
类中,您将拥有 addRbacRole
。只需将角色添加到该实体中即可
/** @var PhpRbacBundle\Core\RoleManager $manager */ $manager = $this->container->get(RoleManager::class); $editorId = $manager->getPathId("/editor"); $editor = $manager->getNode($editorId); $user = $userRepository->find($userId); $user->addRbacRole($user); $userRepository->add($user, true);
要测试用户的权限或角色,请使用 PhpRbacBundle\Core\Rbac 类。
$rbacCtrl = $this->container->get(Rbac::class); $rbacCtrl->hasPermission('/notepad', $userId); $rbacCtrl->hasRole('/editor/reviewer', $userId);
控制器 RBAC
只需添加具有“已授权”属性的属性,如下例所示。属性 IsGranted
和 HasRole
会根据当前用户检查安全性。
namespace App\Controller; ... use PhpRbacBundle\Attribute\AccessControl as RBAC; #[Route('/todolist')] #[RBAC\IsGranted('/notepad/todolist/read')] class TodolistController extends AbstractController { #[RBAC\IsGranted('/notepad/todolist/read')] #[Route('/', name: 'app_todolist_index', methods: ['GET'])] public function index(TodolistRepository $todolistRepository): Response { ... } #[RBAC\IsGranted('/notepad/todolist/write')] #[Route('/new', name: 'app_todolist_new', methods: ['GET', 'POST'])] public function new(Request $request, TodolistRepository $todolistRepository): Response { ... } #[RBAC\IsGranted('/notepad/todolist/read')] #[Route('/{id}', name: 'app_todolist_show', methods: ['GET'])] public function show(Todolist $todolist): Response { ... } #[RBAC\IsGranted('/notepad/todolist/write')] #[Route('/{id}/edit', name: 'app_todolist_edit', methods: ['GET', 'POST'])] public function edit(Request $request, Todolist $todolist, TodolistRepository $todolistRepository): Response { ... } #[RBAC\IsGranted('/notepad/todolist')] #[Route('/{id}', name: 'app_todolist_delete', methods: ['POST'])] public function delete(Request $request, Todolist $todolist, TodolistRepository $todolistRepository): Response { ... } }
类上的第一个 RBAC\IsGranted
检查当前用户访问控制器的最低权限。每个动作上的 RBAC\IsGranted
检查执行动作所需的最小权限。
在示例中
/notepad/todolist/read
权限允许访问所有控制器以及 index 和 show 动作。/notepad/todolist/write
权限允许编辑待办事项列表。- 作为读和写权限父级的
/notepad/todolist
权限允许删除。
/notepad/todolist
权限还具有读和写权限。
基于投票的RBAC
使用RbacVoter,您可以使用symfony安全系统来检查用户的RBAC权限(而非角色)。
示例
#[IsGranted('/todolist/index', statusCode: 403, message: 'Access denied for user')] #[Route('/', name: 'app_todo_list_index', methods: ['GET'])] public function index(TodoListRepository $todoListRepository): Response
您需要将安全访问控制设置为一致(所有投票者都必须同意)。
将以下行添加到 config/packages/security.yaml
security: ... access_decision_manager: strategy: unanimous allow_if_all_abstain: false
Symfony CLI 命令
安装命令设置根节点角色和权限,并将它们关联起来。
security:rbac:install
将权限添加到RBAC权限树中
security:rbac:permission:add
将权限添加到RBAC角色树中
security:rbac:role:add
将权限分配给一个角色
security:rbac:role:assign-permission
将角色分配给一个用户
security:rbac:user:assign-role
这些命令是交互式的。
Twig
测试用户是否拥有某个角色
{% if hasRole('/the/role') %} ... {% endif %}
测试用户是否拥有某个权限
{% if hasPermission('/the/permission') %} ... {% endif %}