Zend Framework: нужен типичный пример ACL

Может ли кто-нибудь подсказать мне типичный пример реализации ACL. Подобно тому, как «администратор» может получить доступ к модулю «админ», «пользователь» может получить доступ к «модулю пользователя», а гость может получить доступ к «открытым» страницам.


person Simpanoz    schedule 06.03.2011    source источник
comment
См. Главный ответ на этот предыдущий вопрос для получения отличного примера реализации: stackoverflow.com/questions/2046608/   -  person Will Prescott    schedule 06.03.2011
comment
Ссылка ZF дает также неплохой пример: framework.zend.com/manual/ ru / zend.acl.refining.html   -  person Laimoncijus    schedule 06.03.2011


Ответы (2)


Я могу вставить вам свой 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);
}
person Marcin    schedule 07.03.2011
comment
Марчин, вы всегда предлагаете новую идею, а сегодняшняя идея - сохранить acl в ini-файле, хорошо, мой друг - person tawfekov; 08.03.2011
comment
@tawfekov. Спасибо :-) Но это не совсем моя идея, поскольку я взял из книги, упомянутой в моем ответе. - person Marcin; 08.03.2011
comment
привет, мы можем управлять контроллерами и действиями с помощью этого кода. как я могу управлять доступом к модулям с помощью этого кода? - person afsane; 16.04.2011
comment
@afsane. В моем примере ресурсы определены как: acl.resources.allow / deny.CONTROLLER.ACTION. Итак, чтобы добавить модуль, вам понадобится что-то вроде acl.resources.allow / deny.MODULE.CONTROLLER.ACTION. Также вам нужно будет изменить класс My_Acl и плагин контроллера Acl, чтобы учесть МОДУЛЬ. - person Marcin; 16.04.2011
comment
ya Marcin, я знаю, но моя проблема: как установить модуль в этом коде $this->allow($role, $controller, $action); я тестировал это как $this->allow($role, $module ,$controller, $action); или $this->allow($role, $module . ':' . $controller, $action);, но они не работают! - person afsane; 16.04.2011
comment
@afsane. Я бы посоветовал задать ТАК вопрос о том, как обрабатывать модули в ACL, так как я себя не очень хорошо знаю. Так что мне тоже было бы интересно, как это сделать правильно. - person Marcin; 17.04.2011
comment
Спасибо! Возникли проблемы с автозагрузкой этого класса, но, наконец, он работает - person Fribu - Smart Solutions; 01.06.2012

У меня есть простой пример, который может удовлетворить ваши потребности

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

}
person tawfekov    schedule 06.03.2011