Chapter 2. Zend_Acl
Prev |  | Next

## Chapter 2. Zend_Acl

## 2.1. Introduction

Zend_Acl provides lightweight and flexible access control list (ACL) functionality and privileges management. In general, an application may utilize such functionality to control access to certain protected objects by other requesting objects.

For the purposes of this documentation,

- a Resource is an object to which access is controlled.

- a Role is an object that may request access to a Resource.

Put simply, Roles request access to Resources. For example, if a person requests access to a car, then the person is the requesting Role, and the car is the Resource, since access to the car is under control.

Through the specification and use of an access control list (ACL), an application may control how requesting objects (Roles) are granted access to protected objects (Resources).

### 2.1.1. About Resources

In Zend_Acl, creating a Resource is very simple. Zend_Acl provides `Zend_Acl_Resource_Interface` to facilitate developers' creating Resources. A class need only implement this interface, which consists of a single method, `getResourceId()`, in order for Zend_Acl to consider the object to be a Resource. Additionally, `Zend_Acl_Resource` is included with Zend_Acl as a basic Resource implementation for developers to extend where desirable.

Zend_Acl provides a tree structure to which multiple Resources (or "areas under access control") can be added. Since Resources are stored in such a tree structure, they can be organized from the general (toward the tree root) to the specific (toward the tree leaves). Queries upon a specific Resource will automatically search the Resource's hierarchy for rules assigned to ancestor Resources, allowing for simple inheritance of rules. For example, if a default rule is to be applied to each building in a city, one would simply assign the rule to the city, instead of assigning the same rule to each building. Some buildings may require exceptions to such a rule, however, and this is achieved easily in Zend_Acl by assigning such exception rules to each such building that requires an exception to the rule. a Resource may inherit from only one parent Resource, though this parent Resource can have its own parent Resource, and so on.

Zend_Acl also supports privileges upon Resources (e.g., "create", "read", "update", "delete"), and the developer can assign rules that affect all privileges or specific privileges upon a Resource.

### 2.1.2. About Roles

Like with Resources, creating a Role is also very simple. Zend_Acl provides `Zend_Acl_Role_Interface` to facilitate developers' creating Roles. A class need only implement this interface, which consists of a single method, `getRoleId()`, in order for Zend_Acl to consider the object to be a Role. Additionally, `Zend_Acl_Role` is included with Zend_Acl as a basic Role implementation for developers to extend where desirable.

In Zend_Acl, a Role may inherit from one or more Roles. This is to support inheritance of rules among Roles. For example, a user Role, such as "sally", may belong to one or more role Roles, such as "editor" and "administrator". The developer can assign rules to "editor" and "administrator" separately, and "sally" would inherit such rules from both, without having to assign rules directly to "sally".

| Note
Since Zend_Acl supports inheriting rules from multiple Roles, which may possibly conflict with each other, a way to unambiguously resolve such conflicts is necessary. Zend_Acl resolves such potential conflicts by considering the most recently inherited Role as highest priority. That is, once a rule is found for a "parent" Role, starting at the most recently inherited Role, no other rules are considered, since the highest priority rule has already been reached.

### 2.1.3. Creating the Access Control List (ACL)

An ACL can represent any set of physical or virtual objects that you wish. For the purposes of demonstration, however, we will create a basic Content Management System ACL that maintains several tiers of groups over a wide variety of areas. To create a new ACL object, we instantiate the ACL with no parameters:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

| Note
Zend_Acl is a "whitelist" implementation by default, which means that unless otherwise specified by the developer, Zend_Acl denies access to every privilege upon every Resource by every Role.

### 2.1.4. Registering Roles

Content Management Systems will nearly always require a hierarchy of permissions to determine the authoring capabilities of its users. There may be a 'Guest' group to allow limited access for demonstrations, a 'Staff' group for the majority of CMS users who perform most of the day-to-day operations, an 'Editor' group for those responsible for publishing, reviewing, archiving and deleting content, and finally an 'Administrator' group whose tasks may include all of those of the other groups as well as maintenance of sensitive information, user management, back-end configuration data and backup/export. This set of permissions can be represented in a Role registry, allowing each group to inherit privileges from 'parent' groups, as well as providing distinct privileges for their unique group only. The permissions may be expressed as follows:

Table 2.1. Access Controls for an Example CMS

Name | Unique permissions | Inherit permissions from
--- | --- | ---
Guest | View | N/A
Staff | Edit, Submit, Revise | Guest
Editor | Publish, Archive, Delete | Staff
Administrator | (Granted all access) | N/A

For this example, `Zend_Acl_Role` is used, but any object that implements `Zend_Acl_Role_Interface` is acceptable. These groups can be added to the Role registry as follows:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

    // Add groups to the Role registry using Zend_Acl_Role
    require_once 'Zend/Acl/Role.php';

    // Guest does not inherit access controls
    $roleGuest = new Zend_Acl_Role('guest');
    $acl->addRole($roleGuest);

    // Staff inherits from guest
    $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);

    /* alternatively, the above could be written:
    $roleGuest = $acl->addRole(new Zend_Acl_Role('staff'), 'guest');
    //*/

    // Editor inherits from staff
    $acl->addRole(new Zend_Acl_Role('editor'), 'staff');

    // Administrator does not inherit access controls
    $acl->addRole(new Zend_Acl_Role('administrator'));

### 2.1.5. Defining Access Controls

Now that the ACL contains the relevant Roles, rules can be established that define how Resources may be accessed by Roles. You may have noticed that we have not defined any particular Resources for this example, which is simplified to illustrate that the rules apply to all Resources. Zend_Acl provides an implementation whereby rules need only be assigned from general to specific, minimizing the number of rules needed, because Resources and Roles inherit rules that are defined upon their ancestors.

Consequently, we can define a reasonably complex set of rules with a minimum amount of code. To apply the base permissions as defined above:

    <?php
    require_once 'Zend/Acl.php';

    $acl = new Zend_Acl();

    require_once 'Zend/Acl/Role.php';

    $roleGuest = new Zend_Acl_Role('guest');
    $acl->addRole($roleGuest);
    $acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
    $acl->addRole(new Zend_Acl_Role('editor'), 'staff');
    $acl->addRole(new Zend_Acl_Role('administrator'));

    // Guest may only view content
    $acl->allow($roleGuest, null, 'view');

    /* alternatively, the above could be written:
    $acl->allow('guest', null, 'view');
    //*/

    // Staff inherits view privilege from guest, but also needs additional privileges
    $acl->allow('staff', null, array('edit', 'submit', 'revise'));

    // Editor inherits view, edit, submit, and revise privileges from staff,
    // but also needs additional privileges
    $acl->allow('editor', null, array('publish', 'archive', 'delete'));

    // Administrator inherits nothing, but is allowed all privileges
    $acl->allow('administrator');

The `null` values in the above `allow()` calls are used to indicate that the allow rules apply to all Resources.

### 2.1.6. Querying the ACL

We now have a flexible ACL that can be used to determine whether requesters have permission to perform functions throughout the web application. Performing queries is quite simple using the `isAllowed()` method:

    <?php
    echo $acl->isAllowed('guest', null, 'view') ?
         "allowed" : "denied"; // allowed

    echo $acl->isAllowed('staff', null, 'publish') ?
         "allowed" : "denied"; // denied

    echo $acl->isAllowed('staff', null, 'revise') ?
         "allowed" : "denied"; // allowed

    echo $acl->isAllowed('editor', null, 'view') ?
         "allowed" : "denied"; // allowed because of inheritance from guest

    echo $acl->isAllowed('editor', null, 'update') ?
         "allowed" : "denied"; // denied because no allow rule for 'update'

    echo $acl->isAllowed('administrator', null, 'view') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

    echo $acl->isAllowed('administrator') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

    echo $acl->isAllowed('administrator', null, 'update') ?
         "allowed" : "denied"; // allowed because administrator is allowed all privileges

Prev |  | Next
1.9. Zend::initRegistry($registry = 'Zend_Registry') | Home | 2.2. Refining Access Controls