gpt4 book ai didi

php - 如何在 Zend Framework 2 中为变量值构建 ACL 断言?

转载 作者:搜寻专家 更新时间:2023-10-31 21:03:21 25 4
gpt4 key购买 nike

我在 acl.global.php 中有一个简单的 ACL 配置,如下所示:

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\Permissions\Acl#allow(...)$this->allow($role, $controller, $action);.

现在我还需要限制用户访问项目的单一 View (mydomain.tld/item/:id)。只有当用户的 id 等于 item.user_id(意味着:用户是作者/所有者)时,用户才应该获得访问权限。

我看到实现这个需求的方式是扩展配置

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

并注入(inject) AssertionZend\Permissions\Acl#allow(...) : $this->allow($role, $controller, $action, $assertion);.

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 === ???;
}
}

但现在我不知道断言应该如何注入(inject) item.user_iddocu 中的示例没有这个问题,因为它针对 $_SERVER['REMOTE_ADDR'] Assets 。

我可以注入(inject) 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_iditem.id)注入(inject)断言?

最佳答案

最后,我通过resource 注入(inject)变量数据解决了这个问题。不要以为这是最干净或推荐的解决方案。无论如何它都有效。但很高兴知道如何以干净/更优雅的方式解决它。

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

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;
}
}

参数化资源

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;
}

}

访问权限

...

// @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

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;
}
}

关于php - 如何在 Zend Framework 2 中为变量值构建 ACL 断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37298894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com