我从zf2开始,必须处理多对多权限/角色。使用ZfcRbac。
所以我用用户/层次角色(表名=角色)/权限进行了映射
我用拒绝政策做了一些警卫。
我的警卫、地图、数据库都很好。
我的层次结构角色实体看起来像:
class HierarchicalRole implements HierarchicalRoleInterface
现在,它和巴库拉提供的原件一样。
我的用户实体如下:
class User extends ZfcUserEntity implements IdentityInterface
带有
/**
* @var DoctrineCommonCollectionsCollection
* @ORMManyToMany(targetEntity="HierarchicalRole")
* @ORMJoinTable(
* name="user_role_linker",
* joinColumns={@ORMJoinColumn(name="user_id", referencedColumnName="idUser")},
* inverseJoinColumns={@ORMJoinColumn(name="role_id", referencedColumnName="id")}
* )
*/
protected $roles;
和角色在构造函数中通过以下方式构建:
function __construct() {
$this->roles = new ArrayCollection();
}
使用zend开发工具,我可以看到ZfcRbacCollectorRbacCollector
显示了我想要的实际登录用户的所有内容(权限、子级、主要角色等)
我的问题是:对于一个只能看到被授予访问权限的链接的用户,如何生成动态导航。并且在用户未登录时检查连接,并在登录时隐藏连接。。。
我还是个新手,但如果可能的话,最好能有一个很好的例子来解释使用这个模块进行良好的动态导航。
编辑(5月28日)到目前为止,我一直在寻找解决方案,但我的尝试对我没有帮助。。你可以在这里找到一个:糟糕的导航仍然不能完美工作。
我将向您展示ZfcRbac如何使用(ZF2)Zend/Navigation。您已经在数据库中定义了权限,所以我将省略这一部分。
定义您的导航添加页面和权限:
config/global.phpPHP:
return array(
'navigation' => array(
'default' => array(
array(
'label' => 'Contracts',
'route' => 'contract',
'action' => 'list',
'permission' => 'contract.list',
'pages' => array(
array(
'label' => 'New contract',
'route' => 'contract',
'action' => 'add',
'permission' => 'contract.add',
)
)
)
)
),
'service_manager' => array(
'factories' => array(
'navigation' => 'ZendNavigationServiceDefaultNavigationFactory',
)
)
);
创建侦听器(/module/Application/src/Application/Authentication/RbacListener.php):
<?php
namespace ApplicationAuthorization;
use ZendEventManagerEventInterface;
use ZendNavigationPageAbstractPage;
use ZfcRbacServiceAuthorizationServiceInterface;
class RbacListener
{
/**
* @var AuthorizationServiceInterface
*/
protected $authorizationService;
/**
* @param AuthorizationServiceInterface $authorizationService
*/
public function __construct(AuthorizationServiceInterface $authorizationService)
{
$this->authorizationService = $authorizationService;
}
/**
* @param EventInterface $event
* @return bool|void
*/
public function accept(EventInterface $event)
{
$page = $event->getParam('page');
if (!$page instanceof AbstractPage) {
return;
}
$permission = $page->getPermission();
if (is_null($permission)) {
$event->stopPropagation();
return false;
}
$event->stopPropagation();
return $this->authorizationService->isGranted($permission);
}
}
为RbacListener创建一个工厂(/module/Application/src/Application/Factory/RbacListenerFactory.php):
<?php
namespace ApplicationFactory;
use ApplicationAuthorizationRbacListener;
use ZendServiceManagerFactoryInterface;
use ZendServiceManagerServiceLocatorInterface;
class RbacListenerFactory implements FactoryInterface
{
/**
* {@inheritDoc}
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$authorizationService = $serviceLocator->get('ZfcRbacServiceAuthorizationService');
return new RbacListener($authorizationService);
}
}
将RbacListenerFactory添加到ServiceManager(/module/Application/config/module.config.php):
<?php
return array(
'service_manager' => array(
'factories' => array(
'ApplicationAuthorizationRbacListener' => 'ApplicationFactoryRbacListenerFactory',
),
),
);
将一个事件附加到Zend Navigation View Helper的isAllowed方法(最后将事件附加到Zend Navigation View Helper的isAllowed方法):
<?php
public function onBootstrap(MvcEvent $event)
{
$application = $event->getApplication();
$eventManager = $application->getEventManager();
$sharedEventManager = $eventManager->getSharedManager;
$serviceManager = $application->getServiceManager();
$rbacListener = $serviceManager->get('ApplicationAuthorizationRbacListener');
$sharedEventManager->attach(
'ZendViewHelperNavigationAbstractHelper',
'isAllowed',
array($rbacListener, 'accept')
);
}
在视图或布局中渲染菜单:
<?php echo $this->navigation('navigation')->menu(); ?>
我正在使用这个代码,它运行得很好。它基于:
http://blog.webdevilopers.net/check-zend-navigation-page-permissions-with-zfcrbac/
http://puzzlingcodes.blogspot.com/2015/05/check-permissions-in-zf2-zendnavigation.html