Navegación Zend y RBAC

I am developing a ZF2 based site. I have a main navigation which stays same regardless of the visitor/user status. Need to add another component/nav, which will depend on the user's status and role. For a visitor the items will be

  • Regístrese
  • Iniciar sesión
  • EN (Actually a drop-down, with other available language)

For a logged-in normal user, it will display

  • Mi Perfil
  • Cerrar sesión
  • EN (Language selector as mentioned above)

And for some users with specific roles/permission there will be additional items

I want to use RBAC, as ACL seems bloated, and also just to check if the current logged in user/role has additional items, I need to load the complete ACL (and we got around 15+ different types of roles).

I spent some time thinking how I have achieve this, so following are some ideas I have.

  1. I create an empty navigation container, and create a factory. In the factory, I access the Authentication and RBAC and add the pages depending on the the user's status/role.
  2. I create a fully loaded navigation with all the possible pages, then in the factory, with the help of Authentication and RBAC I hide the pages I don't want to show.
  3. rd option is to use a view helper which will get RBAC via ServiceLayer and generate the navigation. (As discussed in ZF2 cómo mostrar tweets en el diseño y ZF2: agregue un widget de inicio de sesión en la plantilla.

  4. Or I can create a controller-plugin or just a method in module.php, and listen to the MVC_Render or MVC_Dispatch event and generate the desired navigation and add the output to a view variable.

PS: I need to use a partial as I need to add some CSS class to the language selection section. Also the navigation will be displayed in the layout.

preguntado el 22 de septiembre de 13 a las 09:09

1 Respuestas

Estoy utilizando ZfcRbac and I am doing it as the following, you can display the navigation based on user roles and the navigation items permission as the following:

First add a permission to your navigation item as the following:

'permission' => 'edit-profile',

Then attach a listener in the onBootstrap como el seguiente:

public function onBootstrap(MvcEvent $e)
{
    $eventManager        = $e->getApplication()->getEventManager();
    $eventManager->getSharedManager()->attach(
        'Zend\View\Helper\Navigation\AbstractHelper', 
        'isAllowed', 
        array('\Application\Listener\RbacListener', 'accept')
    );
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);
}

Luego crea una clase Application\Listener\RbacListener como el seguiente:

public function accept(Event $event) { 
    $event->stopPropagation();

    $accepted = true;

    $serviceLocator = $event->getTarget()->getServiceLocator()->getServiceLocator();
    $rbac           = $serviceLocator->get('ZfcRbac\Service\Rbac');

    $params = $event->getParams();
    $page = $params['page'];

    $permission = $page->getPermission();

    if ($permission) {
        $accepted = $rbac->isGranted($permission);
    }

    return $accepted;
}

and by this when you display the menu it will be filtered based on the permission and roles, for example if you do echo $this->navigation('navigation')->menu() then only the menu items that the user has permission on will be displayed.

Respondido el 22 de Septiembre de 13 a las 10:09

Thank you very much for your answer, works like a charm. Could you please clarify a bit about $moduleRouteListener->attach($eventManager); Why do we need this? - write2art

I tried your solution @Mohammad but I get the following error: Strict Standards: call_user_func() expects parameter 1 to be a valid callback, non-static method Application\Listener\RbacListener::accept() should not be called statically in /home/.../zendframework/library/Zend/EventManager/EventManager.php on line 468 - Has something changed with the current versions? - webDEVILopers

Here is short tutorial on the same attempt by @Mohammed ZeinEddin that works with the latest versions of ZF2 and ZfcRbac: blog.webdevilopers.net/?p=9 - webDEVILopers

function accept in RbacListener should be a static one - Ronnie

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.