api-skeletons/zf-oauth2-doctrine-permissions-acl

此软件包已被废弃,不再维护。作者建议使用 api-skeletons/oauth2-doctrine-permissions-acl 软件包。

zf-oauth2-doctrine 的 ACL 权限

2.0.7 2018-10-08 19:29 UTC

This package is auto-updated.

Last update: 2020-07-18 02:04:25 UTC


README

Build Status Gitter Total Downloads

版本

1.x 用于 PHP 5.5 到 7.0。2.x 用于 PHP 7.1 及以上。

关于

此软件包为 api-skeletons/zf-oauth2-doctrine 提供 ACL。它替换了 zfcampus/zf-mvc-auth 的某些组件,以启用每个用户多个角色,并将角色自动注入到 ACL 中。

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

此库依赖于 api-skeletons/zf-oauth2-doctrine-identity。请参阅该库以获取实现细节。

Entity Relationship Diagram

实体关系图由 Skipper 创建

安装

此模块的安装使用 composer。有关 composer 文档,请参阅 getcomposer.org

composer require api-skeletons/zf-oauth2-doctrine-permissions-acl

这将添加到您的应用程序模块列表中

'modules' => array(
   ...
   'ZF\OAuth2\Doctrine\Permissions\Acl',
),

与角色相关的接口

上面的 ERD 显示了 Doctrine 与 Role 实体的关系。要获取用户的角色,用户实体必须实现 ZF\OAuth2\Doctrine\Permissions\Acl\Role\ProviderInterfaceRole 实体必须实现 Zend\Permissions\Acl\Role\RoleInterface

角色可能有父级。这是可选的,但在 ACL 中父级关系通常很重要。要创建角色层次结构,您的角色实体必须实现 ZF\OAuth2\Doctrine\Permissions\Acl\Role\HierarchicalInterface。此接口还实现了 Zend\Permissions\Acl\Role\RoleInterface

将角色添加到 ACL 中

要从您的角色实体将角色复制到 ACL 中,请将 config/oauth2.doctrine.permisisons.acl.global.php.dist 复制到您的应用程序 config/autoload/oauth2.doctrine.permisisons.acl.global.php

'zf-oauth2-doctrine-permissions-acl' => [
    'role' => [
        'entity' => 'Db\Entity\Role',
        'object_manager' => 'doctrine.entitymanager.orm_default',
    ],
],

这将在 MvcAuthEvent::EVENT_AUTHORIZATION 事件中以优先级 1000 运行。如果您不想自动加载角色,请完全删除 'role' 配置。

添加资源保护

通过以上所有设置,该库已经为在您的资源上创建权限奠定了基础。您可以加载所有角色,并遵循官方Apigility指南:[https://apigility.org/documentation/recipes/how-do-i-customize-authorization-for-a-particular-identity](https://apigility.org/documentation/recipes/how-do-i-customize-authorization-for-a-particular-identity) 确保您的监听器(们)运行在优先级小于1000。

这是链接文章的简要概述。

将此引导程序添加到您的模块中。

namespace Application;

use Zend\Mvc\MvcEvent;
use Zend\Mvc\ModuleRouteListener;
use Application\Authorization\AuthorizationListener;
use ZF\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 ZF\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('ZF\OAuth2\Controller\Auth::token');
        $authorization->allow(null, 'ZF\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 ZF\OAuth2\Doctrine\Permissions\Acl\Event;
use Zend\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
);