api-skeletons / oauth2-doctrine-permissions-acl
为Laminas的api-skeletons/oauth2-doctrine-identity提供的ACL权限
Requires
- php: ^7.3
- api-skeletons/oauth2-doctrine: ^5.0
- api-skeletons/oauth2-doctrine-identity: ^5.0.1
- container-interop/container-interop: ^1.1
- gianarb/angry: ^1.0
- laminas/laminas-dependency-plugin: ^2.0
Requires (Dev)
- api-skeletons/coding-standard: ^1.0
- dprevite/lint: dev-master
- laminas-api-tools/api-tools: ^1.3
- laminas-api-tools/api-tools-doctrine: ^2.1
- laminas/laminas-hydrator: ^2.2
- laminas/laminas-i18n: ^2.7
- laminas/laminas-test: ^3.0
- phpstan/phpstan: ^0.9.2
- phpunit/phpunit: ^5.7
- satooshi/php-coveralls: ^1.0
README
关于
此库为api-skeletons/oauth2-doctrine提供了ACL。它替换了laminas-api-tools/api-tools-mvc-auth的一些组件,以实现每个用户可以有多个角色,并将角色自动注入到ACL中。
此库专门用于角色与用户之间的多对多关系。如果您有一个一对一的关系,其中每个用户只能有一个角色,那么此库不适合您。
此库依赖于api-skeletons/auth2-doctrine-identity。请参阅该库的实现细节。
实体关系图由Skipper创建
安装
此模块的安装使用composer。有关composer文档,请参阅getcomposer.org。
composer require api-skeletons/oauth2-doctrine-permissions-acl
这将被添加到您应用程序的模块列表中
'modules' => array( ... 'ApiSkeletons\OAuth2\Doctrine\Permissions\Acl', ),
角色相关接口
上面的ERD显示了Doctrine与Role
实体的关系。要获取用户的角色,用户实体必须实现ApiSkeletons\OAuth2\Doctrine\Permissions\Acl\Role\ProviderInterface
。Role
实体必须实现Laminas\Permissions\Acl\Role\RoleInterface
。
角色可以有父级。这是可选的,但在ACL中父级关系通常很重要。要创建角色层次结构,您的角色实体必须实现ApiSkeletons\OAuth2\Doctrine\Permissions\Acl\Role\HierarchicalInterface
。此接口还实现了Laminas\Permissions\Acl\Role\RoleInterface
。
将角色添加到ACL
要从您的角色实体将角色复制到ACL,请将config/oauth2.doctrine.permisisons.acl.global.php.dist
复制到您的应用程序的config/autoload/oauth2.doctrine.permisisons.acl.global.php
。
'apiskeletons-oauth2-doctrine-permissions-acl' => [ 'role' => [ 'entity' => 'Db\Entity\Role', 'object_manager' => 'doctrine.entitymanager.orm_default', ], ],
这将按优先级1000在MvcAuthEvent::EVENT_AUTHORIZATION
事件中运行。如果您不想自动加载角色,请完全删除'role'配置。
添加资源守卫
以上所述,此库已为您在资源上创建权限奠定了基础。您可以加载所有角色,并遵循官方Apigility指南:[如何自定义特定身份的授权](https://apigility.org/documentation/recipes/how-do-i-customize-authorization-for-a-particular-identity)。确保您的监听器(s)在优先级< 1000下运行。
这是链接文章的简要总结。
将此引导程序添加到您的模块
namespace Application; use Laminas\Mvc\MvcEvent; use Laminas\Mvc\ModuleRouteListener; use Application\Authorization\AuthorizationListener; use Laminas\ApiTools\MvcAuth\MvcAuthEvent; class Module { public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); $eventManager->attach( MvcAuthEvent::EVENT_AUTHORIZATION, new AuthorizationListener(), 100 // Less than 1000 to allow roles to be added first && >= 100 ); } }
创建您的授权监听器
namespace Application\Authorization; use Laminas\ApiTools\MvcAuth\MvcAuthEvent; use Db\Fixture\RoleFixture; class AuthorizationListener { public function __invoke(MvcAuthEvent $mvcAuthEvent) { $authorization = $mvcAuthEvent->getAuthorizationService(); // Deny from all $authorization->deny(); // Allow from all for oauth authentication $authorization->addResource('ApiSkeletons\OAuth2\Controller\Auth::token'); $authorization->allow(null, 'ApiSkeletons\OAuth2\Controller\Auth::token'); // Add application specific resources $authorization->addResource('FooBar\V1\Rest\Foo\Controller::collection'); $authorization->allow(RoleFixture::USER, 'FooBar\V1\Rest\Foo\Controller::collection', 'GET'); } }
重写IS_AUTHORIZED事件
在AclAuthorization上的事件管理器允许您覆盖任何ACL调用。例如,如果您有另一个实体,它需要基于其值进行权限检查,您可以手动添加新的角色到您的ACL中,然后在授权检查时创建覆盖,以便允许那些现在作为角色代理的其他实体值
use ApiSkeletons\OAuth2\Doctrine\Permissions\Acl\Event; use Laminas\EventManager\Event as ZendEvent; // Allow membership as a role $events = $serviceManager->get('SharedEventManager'); $events->attach( Event::class, Event::IS_AUTHORIZED, function(ZendEvent $event) { if (! $event->getParam('identity') instanceof AuthenticatedIdentity) { return; } $membership = $event->getParam('identity')->getUser()->getMembership(); if ($event->getTarget()->isAllowed($membership->getName(), $event->getParam('resource'), $event->getParam('privilege'))) { $event->stopPropagation(); return true; } }, 100 );