api-skeletons/oauth2-doctrine-permissions-acl

为Laminas的api-skeletons/oauth2-doctrine-identity提供的ACL权限

5.0.4 2021-03-31 21:41 UTC

This package is auto-updated.

Last update: 2024-08-29 05:31:00 UTC


README

Build Status Gitter Total Downloads

关于

此库为api-skeletons/oauth2-doctrine提供了ACL。它替换了laminas-api-tools/api-tools-mvc-auth的一些组件,以实现每个用户可以有多个角色,并将角色自动注入到ACL中。

此库专门用于角色与用户之间的多对多关系。如果您有一个一对一的关系,其中每个用户只能有一个角色,那么此库不适合您。

此库依赖于api-skeletons/auth2-doctrine-identity。请参阅该库的实现细节。

Entity Relationship Diagram

实体关系图由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\ProviderInterfaceRole实体必须实现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
);