Table of Contents
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,
Put simply, AROs request access to ACOs. For example, if a person requests access to a car, then the person is the requesting ARO, and the car is the ACO, 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 (AROs) are granted access to protected objects (ACOs).
Zend_Acl provides a tree-based structure to which multiple 'areas' (also known as ACOs) can be added. These 'areas' within the ACL can be assigned either generic or specific 'actions' (known as Contexts) that determine access privileges for user-defined 'groups' (or AROs). These actions are assigned to ACOs ad hoc when calling allow()
or deny()
.
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();
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 an ARO 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 1.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 |
These groups can be added to the ARO registry as follows:
<?php require_once 'Zend/Acl.php'; $acl = new Zend_Acl(); // Retrieve an instance of the ARO registry $aro = $acl->aroRegistry(); // Add groups to the ARO registry // Guest does not inherit access controls $aro->add('guest'); // Staff inherits from guest $aro->add('staff', $aro->guest); // alternatively, $aro->add('staff', 'guest'); // Editor inherits from staff $aro->add('editor', $aro->staff); // Administrator does not inherit access controls $aro->add('administrator');
Now that the ARO registry contains the groups, permissions can be assigned to areas within the ACL. Zend_Acl provides an extremely flexible implementation whereby ACOs need only be created for those areas that require specific permissions. All descendant ACOs - even undeclared ACOs - inherit permissions defined for their ancestor ACOs.
For example, if we assign access controls to $acl->newsletters
, then descendant ACOs such as $acl->newsletters->archive
and $acl->newsletters->pending
inherit access controls from the parent ACO, $acl->newsletters
, despite that they have not been specifically defined for either child ACO.
Consequently, we can define a reasonably complex set of permissions with a minimum amount of code. To apply the base permissions as defined above:
<?php require_once 'Zend/Acl.php'; $acl = new Zend_Acl(); $aro = $acl->aroRegistry(); $aro->add('guest'); $aro->add('staff', $aro->guest); $aro->add('editor', $aro->staff); $aro->add('administrator', $aro->editor); // Whitelist implementation; ACL denies access by default $acl->deny(); // Guest may only view content $acl->allow($aro->guest, 'view'); // alternatively, $acl->allow('guest, 'view'); // Staff inherits view privilege from guest, but also needs additional privileges $acl->allow($aro->staff, array('edit', 'submit', 'revise')); // Editor inherits view, edit, submit, and revise privileges from staff, // but also needs additional privileges $acl->allow($aro->editor, array('publish', 'archive', 'delete')); // Administrator inherits nothing, but is allowed all privileges $acl->allow($aro->administrator);
We now have a flexible ACL that can be used to determine whether requesters have permission to access areas and perform functions throughout the web application. Performing queries can be as flexible as you require:
<?php // Querying the ACL at the root ACO echo $acl->valid($aro->guest, 'view') ? "allowed" : "denied"; // allowed echo $acl->valid($aro->staff, 'publish') ? "allowed" : "denied"; // denied // Permission checks on more specific ACOs echo $acl->newsletter->pending->valid($aro->guest, 'view') ? "allowed" : "denied"; // allowed echo $acl->gallery->profiles->valid($aro->staff, 'revise') ? "allowed" : "denied"; // allowed because of inheritance echo $acl->config->hosts->valid($aro->editor, 'update') ? "allowed" : "denied"; // denied because 'update' is undefined // Querying permissions from the perspective of an ARO echo $aro->staff->canAccess($acl->newsletter->pending, 'view') ? "allowed" : "denied"; // allowed