Need guidance to start with Zend ACL
Asked Answered
U

3

30

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 this. I have read the docs but it confused me further...basically all I want to do is to set up two user groups e.g. "normal" and "admin", normal users can access all pages that have a controller that is not admin while admin can obviously access the admin controller pages.

I have many questions:

  1. How do I set this up?
  2. Should I run it through a DB or the config.ini?
  3. Where do I place my ACL.php?
  4. How do I write such a script?
  5. How do I then call, is this done in the Index?.

I would very much appreciate if you guide me to a website or a good tutorial.

Undersheriff answered 13/2, 2009 at 12:7 Comment(0)
K
38

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);
[...]
Ketch answered 13/2, 2009 at 12:59 Comment(2)
Where does this go in my site structure? APPLICATION controller models views PUBLIC css images js flash LIBRARY zend any advice?Undersheriff
configAcl.php can be anywhere in your Application directory, it's only for inclusion in index.php. AuthPlugin should be in your Library - thus Zend is able to autoload it and you don't have to use require_once. The last statements between [...] depend on your login process...Ketch
Y
2

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;

    }

}
Yokoyama answered 18/11, 2013 at 22:9 Comment(0)
F
2

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

Fucus answered 25/8, 2014 at 5:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.