如何建立在Zend框架2的变量值的ACL断言? [英] How to build an ACL Assertion for a variable value in Zend Framework 2?

查看:337
本文介绍了如何建立在Zend框架2的变量值的ACL断言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的ACL在配置 acl.global.php 是这样的:

I have a simple ACL configures in an acl.global.php like this:

return [
    'acl' => [
        'roles' => [
            'guest' => null,
            'member' => 'guest',
            'admin' => 'member'
        ],
        'resources' => [
            'allow' => [
                'Application\Controller\Index' => ['all' => 'member'],
                'Application\Controller\Error' => ['all' => 'member'],
                'Item\Controller\Process' => [
                    'index' => 'member',
                    'create' => 'member',
                    'showItem' => 'member', // website.tld/item/:id
                    'showList' => 'member' // website.tld/list-items
                ]
            ]
        ],
    ]
];

通过配置解析器迭代,并从数组元素生成调用的 的Zend \\权限\\#的Acl允许(...) $这个 - >允许($角色,$控制器,$行动);

现在我需要再限制用户对项目的单一视图访问( mydomain.tld /项目/:ID )。用户应该只得到访问,如果它的 ID 等于给 item.user_id (意思是:用户是作者/所有者)。

Now I need additionally to restrict the access of the users to the item's single view (mydomain.tld/item/:id). A user should only get the access, if its id equals to the item.user_id (means: the user is the author/owner).

我认为实现这个要求的方法是扩展配置

The way I see to implement this requirement is to extend the config

'Item\Controller\Process' => [
    'index' => 'member',
    'create' => 'member',
    'showItem' => [
        'role' => 'member',
        'assertion' => 'UserIsOwner'
    ]
    'showList' => 'member'
]

和注入<一个href=\"https://github.com/zendframework/zend-permissions-acl/blob/master/src/Assertion/AssertionInterface.php\"相对=nofollow> 断言 来的 的Zend \\权限\\#的Acl允许(...) $这个 - &GT;允许($角色,$控制器,$行动,$断言);

namespace Authorization\Acl\Assertion;
use ...
class UserIsOwner implements AssertionInterface
{
    protected $userId;
    // To inject the $userId can be the job of the factory.
    public function __construct(int $userId)
    {
        $this->userId = $userId;
    }
    public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
    {
        return return $this->userId === ???;
    }
}

但现在我不知道,断言如何获得 item.user_id 注射。在这个例子<一个href=\"http://framework.zend.com/manual/current/en/modules/zend.permissions.acl.advanced.html#writing-conditional-acl-rules-with-assertions\"相对=nofollow>实况没有这个问题,因为它的资产对 $ _ SERVER ['REMOTE_ADDR']

But now I have no idea, how the assertion should get the item.user_id injected. The example in the docu doesn't have this problem, since it assets against the $_SERVER['REMOTE_ADDR'].

我可以注入 ItemService 来找出 item.user_id

public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
{
    return $this->isUserOwner();
}
protected function isUserOwner()
{
    $itemId = ???;
    $item = $this->itemService->findOne($itemId);
    $itemOwnerId = $item->getUser()->getId();
    return $this->userId == $itemOwnerId;
}

虽然那时我还需要外部数据 - 目前的 item.id

在什么地方都可以/应变量项目的数据(在这种情况下, item.user_id item.id )被注入到一个说法?

At what place can/should the variable item's data (in this case the item.user_id or item.id) be injected to an assertion?

推荐答案

最后,我通过通过资源注射可变数据解决了这个问题。不要以为,这是最干净的或推荐的解决方案。反正它的工作原理。但它会很高兴知道,如何解决它清洁/更优雅的方式。

Finally I resolved the problem by injecting the variable data via the resource. Don't think, that it's the cleanest or a recommended solution. Anyway it works. But it would be nice to know, how to resolve it a clean / more elegant way.

UserIsOwner

UserIsOwner

namespace Authorization\Acl\Assertion;

use Zend\Permissions\Acl\Assertion\AssertionInterface;
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\RoleInterface;
use Zend\Permissions\Acl\Resource\ResourceInterface;
use Item\Service\ItemService;

class UserIsOwner implements AssertionInterface
{

    /**
     *
     * @var integer
     */
    protected $userId;

    /**
     *
     * @var ItemService
     */
    protected $itemService;

    public function __construct(int $userId, ItemService $itemService)
    {
        $this->userId = $userId;
        $this->itemService = $itemService;
    }

    public function assert(Acl $acl, RoleInterface $role = null, ResourceInterface $resource = null, $privilege = null)
    {
        return isset($resource->getParams()['id']) ? $this->isUserOwner($resource->getParams()['id']) : false;
    }

    protected function isUserOwner($itemId)
    {
        $item = $this->itemService->findOne($itemId);
        $itemOwnerId = $item->getUser()->getId();
        return $this->userId == $itemOwnerId;
    }

}

UserIsOwnerFactory

UserIsOwnerFactory

namespace Authorization\Acl\Assertion\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Authorization\Acl\Assertion\UserIsOwner;

class UserIsOwnerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $itemFieldsetService = $serviceLocator->get('Item\Service\ItemService');
        $authenticationService = $serviceLocator->get('AuthenticationService');
        $userId = !empty($authenticationService->getIdentity()['id']) ? $authenticationService->getIdentity()['id'] : null;
        $service = new UserIsOwner($userId, $itemFieldsetService);
        return $service;
    }
}

ParametrizedResource

ParametrizedResource

namespace Authorization\Acl\Resource;

use Zend\Permissions\Acl\Resource\GenericResource;
use Zend\Mvc\Router\Http\RouteMatch;

class ParametrizedResource extends GenericResource
{

    /**
     * @var array Params. Here the RouteMatch#params.
     * @see RouteMatch
     */
    protected $params;

    public function __construct($resourceId, array $params = [])
    {
        parent::__construct($resourceId);
        $this->setParams($params);
    }

    /**
     *
     * @return the $params
     */
    public function getParams()
    {
        return $this->params;
    }

    /**
     *
     * @param multitype: $params
     */
    public function setParams($params)
    {
        $this->params = $params;
    }

}

ACL

Acl

...

// @todo refactor
protected function addResources(array $resources)
{
    foreach ($resources as $permission => $controllers) {
        foreach ($controllers as $controller => $actions) {
            if ($controller == 'all') {
                $controller = null;
            } else {
                if (! $this->hasResource($controller)) {
                    $this->addResource(new Resource($controller, $this->routeMatchParams));
                }
            }
            foreach ($actions as $action => $roleConfig) {
                if (is_array($roleConfig)) {
                    foreach ($roleConfig as $role => $assertion) {
                        if ($action == 'all') {
                            $action = null;
                        }
                        $assertion = !empty($this->assertions[$assertion]) ? $this->assertions[$assertion] : null;
                        if ($permission == 'allow') {
                            $this->allow($role, $controller, $action, $assertion);
                        } elseif ($permission == 'deny') {
                            $this->deny($role, $controller, $action, $assertion);
                        } else {
                            throw new \Exception('No valid permission defined: ' . $permission);
                        }
                    }
                } elseif (is_string($roleConfig)) {
                    if ($action == 'all') {
                        $action = null;
                    }
                    if ($permission == 'allow') {
                        $this->allow($roleConfig, $controller, $action);
                    } elseif ($permission == 'deny') {
                        $this->deny($roleConfig, $controller, $action);
                    } else {
                        throw new \Exception('No valid permission defined: ' . $permission);
                    }
                }
            }
        }
    }
    return $this;
}

...

AclFactory

AclFactory

namespace Authorization\Acl\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Authorization\Acl\Acl;

class AclFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config = $serviceLocator->get('Config');
        $assertions = [
            'UserIsOwner' => $serviceLocator->get('Assertion\UserIsOwner')
        ];
        $routeMatch = $serviceLocator->get('Application')->getMvcEvent()->getRouteMatch();
        $routeMatchParams = $routeMatch->getParams();
        $service = new Acl($config, $assertions, $routeMatchParams);
        return $service;
    }
}

这篇关于如何建立在Zend框架2的变量值的ACL断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆