Programmer's Reference Guide
| Refining Access Controls |
Advanced Usage
Storing ACL Data for Persistence
Zend_Acl was designed in such a way that it does not require any particular backend technology such as a database or cache server for storage of the ACL data. Its complete PHP implementation enables customized administration tools to be built upon Zend_Acl with relative ease and flexibility. Many situations require some form of interactive maintenance of the ACL, and Zend_Acl provides methods for setting up, and querying against, the access controls of an application.
Storage of ACL data is therefore left as a task for the developer, since use cases are expected to vary widely for various situations. Because Zend_Acl is serializable, ACL objects may be serialized with PHP's » serialize() function, and the results may be stored anywhere the developer should desire, such as a file, database, or caching mechanism.
Writing Conditional ACL Rules with Assertions
Sometimes a rule for allowing or denying a role access to a resource should not be absolute but dependent upon various criteria. For example, suppose that certain access should be allowed, but only between the hours of 8:00am and 5:00pm. Another example would be denying access because a request comes from an IP address that has been flagged as a source of abuse. Zend_Acl has built-in support for implementing rules based on whatever conditions the developer needs.
Zend_Acl provides support for conditional rules with Zend_Acl_Assert_Interface. In order to use the rule assertion interface, a developer writes a class that implements the assert() method of the interface:
- class CleanIPAssertion implements Zend_Acl_Assert_Interface
- {
- Zend_Acl_Role_Interface $role = null,
- Zend_Acl_Resource_Interface $resource = null,
- $privilege = null)
- {
- return $this->_isCleanIP($_SERVER['REMOTE_ADDR']);
- }
- protected function _isCleanIP($ip)
- {
- // ...
- }
- }
Once an assertion class is available, the developer must supply an instance of the assertion class when assigning conditional rules. A rule that is created with an assertion only applies when the assertion method returns TRUE.
- $acl = new Zend_Acl();
- $acl->allow(null, null, null, new CleanIPAssertion());
The above code creates a conditional allow rule that allows access to all privileges on everything by everyone, except when the requesting IP is "blacklisted." If a request comes in from an IP that is not considered "clean," then the allow rule does not apply. Since the rule applies to all roles, all resources, and all privileges, an "unclean" IP would result in a denial of access. This is a special case, however, and it should be understood that in all other cases (i.e., where a specific role, resource, or privilege is specified for the rule), a failed assertion results in the rule not applying, and other rules would be used to determine whether access is allowed or denied.
The assert() method of an assertion object is passed the ACL, role, resource, and privilege to which the authorization query (i.e., isAllowed()) applies, in order to provide a context for the assertion class to determine its conditions where needed.
| Refining Access Controls |
Add A Comment
Please do not report issues via comments; use the ZF Issue Tracker.
If you have a JIRA/Crowd account, we suggest you login first before commenting.

Comments
require_once('Zend/Acl.php');
/* acl related tables
CREATE TABLE `acl_roles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `acl_resources` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `acl_roles_resources` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`acl_role_id` int(10) unsigned NOT NULL,
`acl_resource_id` int(10) unsigned NOT NULL,
`privilege` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_role_res_priv` (`acl_role_id`,`acl_resource_id`,`privilege`)
);
*/
class MyAcl
{
private $acl = null;
function __construct()
{
$this->acl = new Zend_Acl();
$this->_initRoles();
$this->_initResources();
$this->_initPrivileges();
}
function isAllowed($some_role, $some_resource, $some_privilege)
{
return $this->acl->isAllowed($some_user, $some_resource, $some_action);
}
private function _initRoles()
{
$roles = AclRole::all();
foreach($roles as $role)
{
if($role->parent)
{
$parent = $this->acl->getRole($role->parent->name);
if(is_null($parent))
{
// if parent hasn't been created in memory, do so
$parent = new Zend_Acl_Role($role->parent->name);
$this->acl->addRole($parent);
}
$this->acl->addRole(new Zend_Acl_Role($role->name), $parent);
}
else
{
// only needs to be done if it doesn't exist
if(!$this->acl->hasRole($role->name))
{
$this->acl->addRole(new Zend_Acl_Role($role->name));
}
}
}
}
private function _initResources()
{
$resources = AclResource::all();
foreach($resources as $resource)
{
if($resource->parent)
{
$parent = $this->acl->get($resource->parent->name);
if(is_null($parent))
{
$parent = new Zend_Acl_Resource($resource->parent->name);
$this->acl->addResource($parent);
}
$this->acl->addResource(new Zend_Acl_Resource($resource->name), $parent);
}
else
{
if(!$this->acl->has($resource->name))
{
$this->acl->addResource(new Zend_Acl_Resource($resource->name));
}
}
}
}
private function _initPrivileges()
{
$privileges = AclRolesResource::all();
foreach($privileges as $privilege)
{
// make sure role and resource are valid
if($privilege->acl_role && $privilege->acl_resource)
{
$this->acl->allow($privilege->acl_role->name, $privilege->acl_resource->name, $privilege->privilege);
}
else
{
echo 'WARNING: unable to create privilege
// close the echo and add 4 parens
}
}
}
}
}
// you should be able to paste into any good editor and have it format.
Granted, if you're searching for "Zend_Acl" you probably know what an ACL is, and have some clue as to how to implement one with a DB back-end, but the complete and total lack of examples in the documentation is really, really disappointing.
I feel like if i were in Java World.
Excuse me but Java is not what i need for webApps. In need a framework to develop quickly, not one where i have to do a lot of POC to be sure it run as i want.
The "how's" of it took some time to learn, however it's taken some time, and some trial and error to learn how to do it.
There is enough documentation on Zend Framework here, and out there on the web, to learn how to do it. I hate to say to "ask google" but what you're asking for isn't a single function call. Rather, it's "programming" and it's something you have to put some effort into.
- a 15 year programming veteran
Agree with the comments re: poor docs.
As an analogy, if you buy a camera, the manual won't teach you how to be a great photographer. However, the manual will give photographers all of the information they need to be up and running quickly with that camera.
Hopefully, when I understand enough about how the framework is put together, I'll be able to give some of my time to help out in some way.