2011-03-06 375 views
16

有人可以指导我做ACL的典型实现例子。像'admin'可以访问'admin'模块,'user'可以访问'user module',guest可以访问'open'页面。Zend Framework:需要ACL的典型例子

+0

见上面的回答一个优秀的实现示例这个前面的问题: http://stackoverflow.com/questions/2046608/practical-zend-acl-zend-auth-implementation-and-best-practices – 2011-03-06 13:37:15

+0

ZF的参考给予也不错xample:http://framework.zend.com/manual/en/zend.acl.refining.html – Laimoncijus 2011-03-06 15:32:19

+0

THX,Will Prescott :) – SMka 2011-03-10 13:01:43

回答

4

我有一个简单的例子,可能适合您的需求

class Dagho_Acl_Main extends Zend_Acl { 
    public function __construct() { 
     $anonymous = new Zend_Acl_Role("anonymous"); 
     $customer = new Zend_Acl_Role("customer"); 
     $admin = new Zend_Acl_Role("admin"); 
     $anonymousResource = new Zend_Acl_Resource("acl"); 
     $defaultResource = new Zend_Acl_Resource("default"); 
     $customerResource = new Zend_Acl_Resource("user"); 
     $adminResource = new Zend_Acl_Resource("manage"); 


     $this->addRole($anonymous) 
      ->addRole($customer) 
      ->addRole($admin); 
     $this->addResource($anonymousResource) 
      ->addResource($defaultResource) 
      ->addResource($customerResource) 
      ->addResource($adminResource); 


     $this->allow($anonymous, $anonymousResource); 
     $this->allow($anonymous, $defaultResource); 
     $this->deny($anonymous, $customerResource); 
     $this->deny($anonymous, $adminResource); 

     $this->allow($customer, $anonymousResource); 
     $this->allow($customer, $defaultResource); 
     $this->allow($customer, $customerResource); 
     $this->deny($customer, $adminResource); 

     $this->allow($admin, $defaultResource); 
     $this->allow($admin, $anonymousResource); 
     $this->allow($admin, $adminResource); 
     $this->deny($admin, $customerResource); 
     return $this ; 
    } 
} 

,这里是我的插件:

<?php 

class Dagho_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract { 

    public function preDispatch(Zend_Controller_Request_Abstract $request) { 
     $module = $request->getModuleName(); 
     $controller = $request->getControllerName(); 
     $action = $request->getActionName(); 
     $doctrineAuth = new Dagho_Auth_Doctrine(); 
     $logged = $doctrineAuth->checklogin(); 
     $identity = $doctrineAuth->getIdentity(); 
     Zend_Registry::set("identity", $identity); 
     if ($logged && $identity["role"] !== "anonymous") { 
      /// user had an identity let's check the ACL 
      $acl = new Dagho_Acl_Main(); 
      $isAllowed = $acl->isAllowed($identity["role"], $module); 
      if (!$isAllowed) { 
       return $request->setModuleName("acl")->setControllerName("index") 
         ->setActionName("denied")->setDispatched(true); 
      } else { 
       /// user has identity and he is allowed to access it 
       return; 
      } 
     } elseif ($logged === false || ($logged && $identity["role"] === "anonymous")) { 
      //// user not logged on > login.php or its his first visit 
      $identity = $doctrineAuth->getStorage()->write(array('name' => 'anonymous', 'role' => "anonymous",)); 
      Zend_Registry::set("identity", $identity); 
      return $request->setModuleName("acl")->setControllerName("index") 
        ->setActionName("login")->setDispatched(true); 
     } else { 
      return $request->setModuleName("acl")->setControllerName("index") 
        ->setActionName("denied")->setDispatched(true); 
     } 
     parent::preDispatch($request); 
    } 

} 
27

我可以粘贴你我的ACL。它由三个元素组成:acl.ini,ACL控制器插件(My_Controller_Plugin_Acl)和My_Acl类,以及USER表。但是它不涉及模块,而是涉及控制器和操作。尽管如此,它可能会给你一些有关ACL的一般想法。我对ACL的使用基于一本名为“Zend Framework in Action”的书。

USER表(权限字段用于ACL):

CREATE TABLE IF NOT EXISTS `USER` (
    `user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `email` VARCHAR(85) NOT NULL , 
    `password` CHAR(32) NOT NULL, 
    `phone` VARCHAR(45) NULL , 
    `phone_public` TINYINT(1) NULL DEFAULT 0 ,  
    `first_name` VARCHAR(45) NULL , 
    `last_name` VARCHAR(45) NULL , 
    `last_name_public` TINYINT(1) NULL DEFAULT 1 , 
    `is_enabled` TINYINT(1) NOT NULL DEFAULT 1 , 
    `created` TIMESTAMP NOT NULL, 
    `privilage` ENUM('BASIC','PREMIUM','ADMIN') NOT NULL DEFAULT 'BASIC' , 
    PRIMARY KEY (`user_id`) , 
    UNIQUE INDEX `email_UNIQUE` (`email` ASC)) 
ENGINE = InnoDB; 

acl.ini(我有四个权限,从而从客户基本继承,继承溢价基本形成和管理员溢价):

; roles 
acl.roles.guest = null 
acl.roles.basic = guest 
acl.roles.premium = basic 
acl.roles.administrator = premium 

; resources 
acl.resources.deny.all.all = guest 


acl.resources.allow.index.all = guest 
acl.resources.allow.error.all = guest 
acl.resources.allow.user.login = guest 
acl.resources.allow.user.logout = guest 
acl.resources.allow.user.create = guest 

acl.resources.allow.user.index = basic 
acl.resources.allow.user.success = basic 

My_Acl类(ACL创建角色和基于ini文件资源):

class My_Acl extends Zend_Acl { 

    public function __construct() { 
     $aclConfig = Zend_Registry::get('acl'); 
     $roles = $aclConfig->acl->roles; 
     $resources = $aclConfig->acl->resources; 
     $this->_addRoles($roles); 
     $this->_addResources($resources); 
    } 

    protected function _addRoles($roles) { 

     foreach ($roles as $name => $parents) { 
      if (!$this->hasRole($name)) { 
       if (empty($parents)) { 
        $parents = null; 
       } else { 
        $parents = explode(',', $parents); 
       }      
       $this->addRole(new Zend_Acl_Role($name), $parents);    
      } 
     }  
    } 

    protected function _addResources($resources) {   

     foreach ($resources as $permissions => $controllers) {   

      foreach ($controllers as $controller => $actions) { 
       if ($controller == 'all') { 
        $controller = null; 
       } else { 
        if (!$this->has($controller)) { 
         $this->add(new Zend_Acl_Resource($controller)); 
        } 
       } 

       foreach ($actions as $action => $role) { 
        if ($action == 'all') { 
         $action = null; 
        } 
        if ($permissions == 'allow') { 
         $this->allow($role, $controller, $action); 
        } 
        if ($permissions == 'deny') {       
         $this->deny($role, $controller, $action); 
        } 
       } 
      } 
     } 
    } 

} 

My_Controller_Plugin_Acl

class My_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract { 

    /** 
    * 
    * @var Zend_Auth 
    */ 
    protected $_auth; 

    protected $_acl; 
    protected $_action; 
    protected $_controller; 
    protected $_currentRole; 

    public function __construct(Zend_Acl $acl, array $options = array()) { 
     $this->_auth = Zend_Auth::getInstance(); 
     $this->_acl = $acl; 

    } 

    public function preDispatch(Zend_Controller_Request_Abstract $request) { 

     $this->_init($request);   

     // if the current user role is not allowed to do something 
     if (!$this->_acl->isAllowed($this->_currentRole, $this->_controller, $this->_action)) { 

      if ('guest' == $this->_currentRole) { 
       $request->setControllerName('user'); 
       $request->setActionName('login'); 
      } else { 
       $request->setControllerName('error'); 
       $request->setActionName('noauth'); 
      } 
     } 
    } 

    protected function _init($request) { 
     $this->_action = $request->getActionName(); 
     $this->_controller = $request->getControllerName(); 
     $this->_currentRole = $this->_getCurrentUserRole(); 
    } 

    protected function _getCurrentUserRole() {  

     if ($this->_auth->hasIdentity()) { 
      $authData = $this->_auth->getIdentity(); 
      $role = isset($authData->property->privilage)?strtolower($authData->property->privilage): 'guest'; 
     } else { 
      $role = 'guest'; 
     } 

     return $role; 
    } 

} 

最后,一切被初始化bootstrap.php中的一部分:

protected function _initLoadAclIni() { 
    $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/acl.ini'); 
    Zend_Registry::set('acl', $config); 
} 

protected function _initAclControllerPlugin() { 
    $this->bootstrap('frontcontroller'); 
    $this->bootstrap('loadAclIni'); 

    $front = Zend_Controller_Front::getInstance(); 

    $aclPlugin = new My_Controller_Plugin_Acl(new My_Acl()); 

    $front->registerPlugin($aclPlugin); 
} 
+0

Marcin,你总是提出一个新想法,今天的想法是在ini文件中保存acl,做好我的朋友 – tawfekov 2011-03-08 14:14:56

+0

@tawfekov。谢谢:-)但是,这并不完全是我的想法,因为我从我的答案中提到的书中拿走了。 – Marcin 2011-03-08 15:25:09

+0

嗨,我们可以用这个代码管理控制器和操作。如何使用此代码管理模块访问? – afsane 2011-04-16 09:39:47