Need guidance to start with Zend ACL

后端 未结 3 1760
独厮守ぢ
独厮守ぢ 2020-12-04 09:03

I am currently working on a site that requires ACL and as I am using Zend, it makes sense for me to make use of their ACL class but I have little to zero idea of how to do t

相关标签:
3条回答
  • 2020-12-04 09:07

    I implemented similar thing not so long ago. Basic concept follows in an example code.

    I created my own configAcl.php file which is loaded in bootstrap file, in my case it is index.php. Here is how it'd be according to your case:

    $acl = new Zend_Acl();
    
    $roles  = array('admin', 'normal');
    
    // Controller script names. You have to add all of them if credential check
    // is global to your application.
    $controllers = array('auth', 'index', 'news', 'admin');
    
    foreach ($roles as $role) {
        $acl->addRole(new Zend_Acl_Role($role));
    }
    foreach ($controllers as $controller) {
        $acl->add(new Zend_Acl_Resource($controller));
    }
    
    // Here comes credential definiton for admin user.
    $acl->allow('admin'); // Has access to everything.
    
    // Here comes credential definition for normal user.
    $acl->allow('normal'); // Has access to everything...
    $acl->deny('normal', 'admin'); // ... except the admin controller.
    
    // Finally I store whole ACL definition to registry for use
    // in AuthPlugin plugin.
    $registry = Zend_Registry::getInstance();
    $registry->set('acl', $acl);
    

    Another case is if you want to allow normal user only "list" action on all your controllers. It's pretty simple, you'd add line like this:

    $acl->allow('normal', null, 'list'); // Has access to all controller list actions.
    

    Next you should create new plugin which takes care of credential checking automatically when there is a request for some controller action. This checking takes place in preDispatch() method that is called before every call to the controller action.

    Here is AuthPlugin.php:

    class AuthPlugin extends Zend_Controller_Plugin_Abstract
    {
        public function preDispatch(Zend_Controller_Request_Abstract $request)
        {
            $loginController = 'auth';
            $loginAction     = 'login';
    
            $auth = Zend_Auth::getInstance();
    
            // If user is not logged in and is not requesting login page
            // - redirect to login page.
            if (!$auth->hasIdentity()
                    && $request->getControllerName() != $loginController
                    && $request->getActionName()     != $loginAction) {
    
                $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
                $redirector->gotoSimpleAndExit($loginAction, $loginController);
            }
    
            // User is logged in or on login page.
    
            if ($auth->hasIdentity()) {
                // Is logged in
                // Let's check the credential
                $registry = Zend_Registry::getInstance();
                $acl = $registry->get('acl');
                $identity = $auth->getIdentity();
                // role is a column in the user table (database)
                $isAllowed = $acl->isAllowed($identity->role,
                                             $request->getControllerName(),
                                             $request->getActionName());
                if (!$isAllowed) {
                    $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
                    $redirector->gotoUrlAndExit('/');
                }
            }
        }
    }
    

    Final steps are loading your configAcl.php and register the AuthPlugin in bootstrap file (probably index.php).

    require_once '../application/configAcl.php';
    
    $frontController = Zend_Controller_Front::getInstance();
    $frontController->registerPlugin(new AuthPlugin());
    

    So this is the basic concept. I didn't test the code above (copy and paste and rewrite just for the showcase purpose) so it's not bullet-proof. Just to give an idea.

    EDIT

    For the clarity. The code above in AuthPlugin suppose that the $identity object is filled with user data ("role" column in the database). This could be done within the login process like this:

    [...]
    $authAdapter = new Zend_Auth_Adapter_DbTable($db);
    $authAdapter->setTableName('Users');
    $authAdapter->setIdentityColumn('username');
    $authAdapter->setCredentialColumn('password');
    $authAdapter->setIdentity($username);
    $authAdapter->setCredential(sha1($password));
    $authAdapter->setCredentialTreatment('? AND active = 1');
    $auth = Zend_Auth::getInstance();
    $result = $auth->authenticate($authAdapter);
    if ($result->isValid()) {
        $data = $authAdapter->getResultRowObject(null, 'password'); // without password
        $auth->getStorage()->write($data);
    [...]
    
    0 讨论(0)
  • 2020-12-04 09:16

    This solution may prove to be the simplest implementation of Zend_Acl.

    Example:

    class UserController extends Zend_Controller_Action {
    
        public function preDispatch(){
    
            $resource = 'user_area';
            $privilege = $this->_request->getActionName();
            if (!$this->_helper->acl($resource, $privilege)) $this->_redirect();
    
        }
    
    }
    

    Zend/Controller/Action/Helper/Acl.php

    class Zend_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract {
    
        protected $acl;
        protected $role;
    
        protected function getAcl(){
    
            if (is_null($this->acl)){
    
                $acl = new Zend_Acl();
    
                $acl->addResource(new Zend_Acl_Resource('user_area'));
                $acl->addResource(new Zend_Acl_Resource('customer_area'), 'user_area');
                $acl->addResource(new Zend_Acl_Resource('web_area'));
    
                $acl->addRole(new Zend_Acl_Role('guest'));      
                $acl->addRole(new Zend_Acl_Role('user'), 'guest');
    
                $acl->allow('guest', 'web_area');
                $acl->allow('guest', 'user_area', array(
                    'forgot-password',
                    'login'
                ));
                $acl->allow('user', 'user_area');
                $acl->allow('customer', 'customer_area');
    
                $this->acl = $acl;
    
            }
    
            return $this->acl;
    
        }
    
        protected function getRole(){
    
            if (is_null($this->role)){
    
                $session = new Zend_Session_Namespace('session');
                $role = (isset($session->userType)) ? $session->userType : 'guest';
                $this->role = $role;
    
            }
    
            return $this->role;
    
        }
    
        public function direct($resource, $privilege = null){
    
            $acl = $this->getAcl();
            $role = $this->getRole();
            $allowed = $acl->isAllowed($role, $resource, $privilege);
            return $allowed;
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-04 09:26

    Play with This structure . get role and resource from database and save this in session for or any caching . enter image description here

    0 讨论(0)
提交回复
热议问题