Search code examples
zend-frameworkpartial-viewszend-authzend-acl

How do I combine Zend_Ath, Zend_Acl and partialview for the authentication and resource control


According to Randomness will get you everywhere. Ryan’s Blog the action stack component of Zend Framework is un-needed and that a partial view can be combined with Zend_Acl and Zend_Auth for the purpose of authenticating and controlling resources.

I have not been able to find any suitable example on google about how its done. Will be glad is someone will be kind to show me how to implement this. Thanks


Solution

  • Here you go:

    You could use the combination of Zend_Auth and Zend_Acl. To extend the other answers I give a short example of how you can manage authentication using zend framework:

    First you need to setup a plugin to predispatch all requests and check if the client is allowed to access certain data. This plugin might look like this one:

    class Plugin_AccessCheck extends Zend_Controller_Plugin_Abstract {
    
        private $_acl = null;
    
        public function __construct(Zend_Acl $acl) {
            $this->_acl = $acl;
        }
    
        public function preDispatch(Zend_Controller_Request_Abstract $request) {
            //get request information
            $module = $request->getModuleName ();
            $resource = $request->getControllerName ();
            $action = $request->getActionName ();
    
            try {
                if(!$this->_acl->isAllowed(Zend_Registry::get('role'), 
                                    $module . ':' . $resource, $action)){
                    $request->setControllerName ('authentication')
                            ->setActionName ('login');
                }
            }catch(Zend_Acl_Exception $e) {
                $request->setControllerName('index')->setActionName ('uups');
            }
        }
    }
    

    So every user type has certain permissions that you define in your acl library. On every request you check if the user is allowed to access a resource. If not you redirect to login page, else the preDispatch passes the user to the resource.

    In Zend_Acl you define roles, resources and permission, that allow or deny access, e.g.:

    class Model_LibraryAcl extends Zend_Acl {
        public function __construct() {
    
            $this->addRole(new Zend_Acl_Role('guests'));
            $this->addRole(new Zend_Acl_Role('users'), 'guests');
            $this->addRole(new Zend_Acl_Role('admins'), 'users');                
    
            $this->add(new Zend_Acl_Resource('default'))
                 ->add(new Zend_Acl_Resource('default:authentication'), 'default')
                 ->add(new Zend_Acl_Resource('default:index'), 'default')
                 ->add(new Zend_Acl_Resource('default:error'), 'default');
    
            $this->allow('guests', 'default:authentication', array('login'));
            $this->allow('guests', 'default:error', 'error');
    
            $this->allow('users', 'default:authentication', 'logout');          
        }
    }
    

    Then you have to setup acl and auth in your bootstrap file:

        private $_acl = null;
    
        protected function _initAutoload() {
    
           //...your code           
           if (Zend_Auth::getInstance()->hasIdentity()){
            Zend_Registry::set ('role',
                         Zend_Auth::getInstance()->getStorage()
                                                  ->read()
                                                  ->role);
            }else{
                Zend_Registry::set('role', 'guests');
            }
    
            $this->_acl = new Model_LibraryAcl ();
            $fc = Zend_Controller_Front::getInstance ();
            $fc->registerPlugin ( new Plugin_AccessCheck ( $this->_acl ) );
    
            return $modelLoader;
        }
    

    Finally in your authentication controller you have to use a custom auth adapter and setup actions for login and logout:

    public function logoutAction() {
        Zend_Auth::getInstance ()->clearIdentity ();
        $this->_redirect ( 'index/index' );
    }
    
    private function getAuthAdapter() {
        $authAdapter = new Zend_Auth_Adapter_DbTable ( 
                            Zend_Db_Table::getDefaultAdapter ());
        $authAdapter->setTableName('users')
                    ->setIdentityColumn('email')
                    ->setCredentialColumn ('password')
                    ->setCredentialTreatment ('SHA1(CONCAT(?,salt))');
    
        return $authAdapter;
    }
    

    In your login action you need to pass login data to the auth adapter which performs the authentication.

    $authAdapter = $this->getAuthAdapter ();
    $authAdapter->setIdentity ( $username )->setCredential ( $password );
    $auth = Zend_Auth::getInstance ();
    $result = $auth->authenticate ( $authAdapter );
    
    if ($result->isValid ()) {
        $identity = $authAdapter->getResultRowObject ();
        if ($identity->approved == 'true') {
            $authStorage = $auth->getStorage ();
            $authStorage->write ( $identity );
            $this->_redirect ( 'index/index' );
        } else {
           $this->_redirect ( 'authentication/login' );
      }
    

    And that's all. I recommend you this HOW TO on youtube on zend auth and zend acl.