Programmer's Reference Guide
| Affiner les Contrôles d'Accès |
Utilisation avancée
Rendre les données ACL persistantes
Zend_Acl a été conçu pour ne pas nécessiter de technologie spécifique comme une base de données ou un serveur de cache pour conserver les données ACL. Son implémentation PHP permet de créer des outils d'administration basés sur Zend_Acl assez facilement. De nombreuses situations nécessitent une certaine forme de maintenance ou de gestion des ACL, et Zend_Acl fournit les méthodes pour définir et interroger les règles d'accès d'une application.
Le stockage des données ACL est dès lors laissé aux bons soins du développeur, dans la mesure où les cas d'utilisation peuvent grandement varier d'un cas à l'autre. Puisque Zend_Acl est sérialisable, les objets ACL peuvent être sérialisés avec la fonction » serialize() de PHP, et le résultat peut être stocké n'importe où le développeur le désire : fichier, base de donnée, cache.
Écrire des règles ACL conditionnelles avec des assertions
Parfois, une règle pour autoriser ou interdire l'accès d'un rôle à une ressource n'est pas absolu, mais dépend de plusieurs critères. Par exemple, supposons qu'un certain accès peut être autorisé, mais uniquement entre 8h du matin et 5h du soir. Un autre exemple consisterait à interdire l'accès parce que la requête provient d'une adresse IP qui est notée comme source d'abus. Zend_Acl dispose d'un support intégré pour implémenter des règles sur quoique ce soit dont le développeur ait besoin.
Zend_Acl fourni le support pour les règles conditionnelles via Zend_Acl_Assert_Interface. Pour mettre en oeuvre cette interface, il suffit d'implémenter la méthode assert() :
- 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)
- {
- //...
- }
- }
Lorsqu'une classe d'assertion est disponible, le développeur doit fournir une instance de cette classe lorsqu'il assigne une règle conditionnelle. Une règle qui est créée avec une assertion s'applique uniquement dans les cas où l'assertion retourne une valeur TRUE.
- $acl = new Zend_Acl();
- $acl->allow(null, null, null, new CleanIPAssertion());
Le code ci-dessus crée une règle conditionnelle qui autorise l'accès à tous les privilèges, sur tout et pour tout le monde, sauf lorsque l'adresse IP de la requête fait partie de la liste noire. Si une requête provient d'une adresse IP qui n'est pas considérée comme "propre", alors la règle d'autorisation ne s'applique pas. Puisque la règle s'applique à tous les rôles, toutes les Ressources, et tous les privilèges, une IP "sale" aboutira à un refus d'accès. Ceci constitue un cas spécial, et il faut bien noter que tous les autres cas (donc, si un rôle, une ressource ou un privilège est défini pour la règle), une assertion qui échoue aboutit à une règle qui ne s'applique pas et ce sont alors les autres règles qui servent à déterminer si l'accès est autorisé ou non.
La méthode assert() d'un objet d'assertion reçoit l'ACL, le rôle, la ressource et le privilège auquel une requête d'autorisation (c.-à-d., isAllowed()) s'applique, afin de fournir un contexte à la classe d'assertion pour déterminer ses conditions lorsque cela est nécessaire.
| Affiner les Contrôles d'Accès |
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.