2443

ACL Ressource (Controller)

Question:

i just implemented ACL in my Zend Framework which already uses Zend Auth.

I want to give access to some controllers and tried it this way:

$roleGuest = new Zend_Acl_Role('guest'); $this->addRole($roleGuest); $this->addRole(new Zend_Acl_Role('supplier')); $this->addRole(new Zend_Acl_Role('admin')); $this->add(new Zend_Acl_Resource('Articles')); $this->add(new Zend_Acl_Resource('Index')); $this->deny(); $this->allow('supplier', 'Articles'); $this->allow('admin', null);

But a user, who is supplier (he is really :)) is not able to see the Controller Articles. What am I doing wrong?

Thanks for help.

BR frgtv10

Answer1:

I think the best solution is to create a plugin and write something like this

class Application_Controller_Plugin_AclManager extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $Request) { $AclManager = new Zend_Acl(); $AclManager->addRole(new Zend_Acl_Role('Guest')); $AclManager->addRole(new Zend_Acl_Role('Supplier'), 'Guest'); $AclManager->addResource(new Zend_Acl_Resource('controller1')); $AclManager->addResource(new Zend_Acl_Resource('controller2')); $AclManager->addResource(new Zend_Acl_Resource('controller3')); $AclManager->allow('Guest', 'controller1', 'index'); $AclManager->allow('Supplier', 'controller2'); $AclManager->allow('Supplier', 'controller3');

It will work great. In addition you can write

if (! $AclManager->isAllowed(USER_ROLE, $Request->getControllerName(), $Request->getActionName())) { $this->getResponse()->setRedirect(SOME_URL_TO_REDIRECT); }

Answer2:

The approach from user707795 is good. I build up my resources with Pike_Reflection_Resource to automaticly define your resources. It's not perfectly documented yet but usage is very simple:

You download the latest version of the Pike library <a href="http://code.google.com/p/php-pike/" rel="nofollow">http://code.google.com/p/php-pike/</a>

Then you create a ACL class which extends Zend_Acl:

<?php class Application_Acl extends Zend_Acl { /** * Constructor */ public function __construct() { $this->_addRoles(); $this->_addResources(); $this->_setAuthorization(); } /** * Adds roles to ACL */ protected function _addRoles() { /** * Get your roles from the application config here or the database like below (Doctrine2) */ // $repository = $this->_em->getRepository('BestBuy\Entity\Usergroup'); $roles = array('guest', 'admin', 'moderator'); foreach($roles as $role) { $this->addRole(new Zend_Acl_Role(strtolower($role))); } } /** * Adds resources to ACL * * Here are resources added to the ACL. You don't have to do this manually * because Pike_Reflection_Resource will search automaticly in your controller * directories to define which actions there are and adds every resource as: * modulename_controller_actionname all lowercase. */ public function _addResources() { $resourceReflection = new Pike_Reflection_Resource(); $resources = $resourceReflection->toFlatArray('default'); foreach ($resources as $resource => $humanValue) { $this->addResource(new Zend_Acl_Resource($resource)); } } /** * Sets authorization */ public function _setAuthorization() { //$permissions = $this->_em->getRepository('BestBuy\Entity\Permission')->findAll(); /** * I retrieve my permissions here from the database but you could receive the * from the roles attribute too: */ $resourceReflection = new Pike_Reflection_Resource(); $resources = $resourceReflection->toArray('default'); foreach ($resources as $moduleName => $controllers) { foreach($controllers as $controllerName=>$actions) { foreach($actions as $actionName=>$action) { $resourceName = sprintf('%s_%s_%s', strtolower($moduleName), strtolower($controllerName), strtolower($actionName) ); if(isset($action['roles'])) { foreach($action['roles'] as $role) { if ($this->hasRole($role) && $this->has($resourceName)) { $this->allow($role, $resourceName); } } } } } } } } ?>

Then you set up a frontcontroller plugin something just like above:

<?php class Application_Controller_Plugin_Authorization extends Zend_Controller_Plugin_Abstract { /** * Request * * @var Zend_Controller_Request_Abstract */ protected $_request; /** * ACL * * @var Buza_Acl */ protected $_acl; /** * Called before Zend_Controller_Front enters its dispatch loop. * * @param Zend_Controller_Request_Abstract $request * @return void */ public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) { $this->_request = $request; $this->_acl = new Application_Acl(); Zend_Registry::set('acl', $this->_acl); $this->_checkAuthorization(); } /** * Checks if the current user is authorized */ protected function _checkAuthorization() { $allowed = false; $currentResource = sprintf('%s_%s_%s', strtolower($this->_request->getModuleName()), strtolower($this->_request->getControllerName()), strtolower($this->_request->getActionName()) ); if(Zend_Auth::getInstance()->hasIdentity()) { $user = Zend_Auth::getInstance()->getIdentity()); $identityRole = strtolower($user->getRole()); //make sure you implement this function on your user class/identity! } else { $identityRole = 'guest'; } if ($this->_acl->hasRole($identityRole) && $this->_acl->has($currentResource)) { if ($this->_acl->isAllowed($identityRole, $currentResource)) { $allowed = true; } } if ($allowed !== true) { throw new Zend_Controller_Exception('No permission', 403); } } } ?>

Finally in your controller/actions you define your permissions as follows:

<?php class IndexController extends Zend_Controller_Action { /** * @human Some description for the permissions of this action * @roles guest|admin|moderator */ public function indexAction() { } /** * @human Only for admins! * @roles admin */ public function secretAction() { } } ?>

This approach is the best and set-up for small applications. For applications where you want to define the allowed actions in the interface of the application you should leave the roles tag and get the permissions for the database.

Please be aware that code below is not tested but with some reviewing it will work and you can control your permissions in the code.

Recommend

  • How to show a decimal corretly formatted in 0.00$ format?
  • how to set bug tracker url in setup.py script
  • How do you convert an aspx or master page file to page and code behind?
  • Google API Oauth php permanent access
  • Link conversion in mod rewrite .htaccess
  • How do I create an image and save it for later to draw as texture in XNA?
  • What is the equivalent of Android permissions in iOS development? [duplicate]
  • sudo easy_install for SimpleITK not that easy
  • Linking Ghostscript to pypdfocr in Windows Platform
  • in batch how do i use taskkill properly
  • jersey/tomcat Description The origin server did not find a current representation for the target res
  • Portable JRE on Linux - possible?
  • Bash if statement with multiple conditions
  • saving file generated by TCPDF
  • JBoss External Properties Files in Classpath
  • Not able to aggregate on nested fields in elasticsearch
  • Unable to install Git-core+svn by MacPorts
  • C: Incompatible pointer type initializing
  • Django simple Captcha “No module named fields” error
  • print() is showing quotation marks in results
  • Content-Length header not returned from Pylons response
  • Sencha Touch 2.0 Controller refs attribute not working?
  • VSO Build — Response status code does not indicate success: 404 (Not Found)
  • Could not find rake using whenever rails
  • Python urlparse: small issue
  • When to use `image` and when to use `Matrix` in Emgu CV?
  • Installing Hadoop, Java Exception about illegal characters at index 7?
  • What is the “return” in scheme?
  • Different response to non-authenticated users and AJAX calls
  • C# - Serializing and deserializing static member
  • Incrementing object id automatically JS constructor (static method and variable)
  • Can I make an Android app that runs a web view in Chrome 39?
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • Convert array of 8 bytes to signed long in C++
  • Do create extension work in single-user mode in postgres?
  • -fvisibility=hidden not passed by compiler for Debug builds
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • Net Present Value in Excel for Grouped Recurring CF