Zend Framework - Gestion des accès avec Zend Auth et Zend Acl
Au sujet des classes de base, je ne vais pas réexpliquer ce que sont Zend_Auth et Zend_Acl car la documentation officielle le fait déjà parfaitement. Par contre, ce que la documentation officielle ne fait pas, c'est nous soumettre un cas pratique pour la gestion des accès sur notre site. C'est ce que je vais tenter de vous présenter ici.
Tout d'abord, il est essentiel de bien comprendre ce schéma que j'ai déjà proposé dans mon article de le plugin d'initialisation et également de bien comprendre les plugins et helpers.
Composants
Nous allons travailler avec 4 composants bien distincts que je décris dans les chapitres suivants.
My_Acl
Cette classe, héritée de Zend_Acl, servira à charger les rôles,
ressources et permissions tels qu'on les aura définis. Elle répond à la
question "Comment configurer mes droits d'accès ?".
Je vous propose
ci-dessous un exemple de classe qui permet la gestion de droit dans un
fichier INI. Libre à vous d'imaginer comment charger ces droits depuis
une base de données ou autres. Vous pouvez également définir les droits
directement dans la classe, mais ça, je ne saurais vous le conseiller.
L'appel
de la classe se fait lors de l'initialisation de votre application,
dans le bootstrap, puis est passée en paramètre dans le plugin de
gestion des accès (prochain chapitre) :
$acl_ini = '../config/acl.ini' ; $acl = new My_Acl_Ini($acl_ini) ;
Le fichier INI est construit ainsi :
[roles] guest = null member = null admin = null [ressources] ; définition des ressources dans le module par défaut index = null login = null products = null member = null ; définition des ressources dans le module de blog blog_index = null [guest] allow.login = null allow.index = null allow.products = list,view allow.member = subscribe allow.blog_index = list,view ; member hérite de guest [member : guest] ; on interdit le login (le membre est déjà identifié) deny.login = null allow.member = index,orders allow.blog_index = comment ; admin hérite de member [admin : member] allow.admin = null
La section des roles contient... les rôles et après le signe = le rôle dont il hérite. Mais dans mon exemple, j'ai préféré gérer l'héritage par la structure de groupe proposée par Zend_Config_Ini.
La section des ressources est organisée de manière identique. Le nom de la ressource correspond au nom du contrôleur d'action. On gère également les modules en préfixant le nom du contrôleur par le nom du module. Le module par défaut n'est pas spécifié.
Ensuite, une section est créée pour chaque rôle afin de définir les accès sur leurs permissions sur les ressources. La permission est accordée (allow) ou non (deny). Après le signe = nous retrouvons les actions auxquelles le rôle a le droit d'accéder. "null" signifie qu'il a les droits d'accès sur la totalité des actions du contrôleur.
La classe que je vous propose initialise chacun des rôles sans aucun droit. Il est donc obligatoire de tous les définir. Ca peut paraitre rébarbatif mais ça évite bien des problèmes et trous de sécurité !
Je n'ai pas copié la totalité du code de la classe afin d'éviter la pollution de cette page. Vous pouvez télécharger le code complet ici.
My_Controller_Plugin_Auth
C'est ici une des parties intéressantes de cet article. La réponse à la question : "Où et quand je vais contrôler l'accès ?". Et la réponse est simple : avant le processus de dispatching de la requête. C'est à dire avant que le contrôleur d'action soit appelé mais après le routage de la requête. A ce moment nous connaissons le contrôleur appelé et l'action appelée. Nous pouvons toutefois encore rediriger la requête vers un autre contrôleur, si nécessaire.
Ce plugin est composé d'une méthode que je recopie ci-dessous :
/**
* Vérifie les autorisations
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
// is the user authenticated
if ($this->_auth->hasIdentity()) {
// yes ! we get his role
$user = $this->_auth->getStorage()->read() ;
$role = $user['role'] ;
} else {
// no = guest user
$role = 'guest';
}
$module = $request->getModuleName() ;
$controller = $request->getControllerName() ;
$action = $request->getActionName() ;
$front = Zend_Controller_Front::getInstance() ;
$default = $front->getDefaultModule() ;
// compose le nom de la ressource
if ($module == $default) {
$resource = $controller ;
} else {
$resource = $module.'_'.$controller ;
}
// est-ce que la ressource existe ?
if (!$this->_acl->has($resource)) {
$resource = null;
}
// contrôle si l'utilisateur est autorisé
if (!$this->_acl->isAllowed($role, $resource, $action)) {
// l'utilisateur n'est pas autorisé à accéder à cette ressource
// on va le rediriger
if (!$this->_auth->hasIdentity()) {
// il n'est pas identifié -> module de login
$module = self::FAIL_AUTH_MODULE ;
$controller = self::FAIL_AUTH_CONTROLLER ;
$action = self::FAIL_AUTH_ACTION ;
} else {
// il est identifié -> error de privilèges
$module = self::FAIL_ACL_MODULE ;
$controller = self::FAIL_ACL_CONTROLLER ;
$action = self::FAIL_ACL_ACTION ;
}
}
$request->setModuleName($module) ;
$request->setControllerName($controller) ;
$request->setActionName($action) ;
}
Vous pouvez télécharger le code complet ici.
Ce plugin est initialisé dans votre bootstrap
// $auth est une référence vers Zend_Auth (getInstance()) // $acl a été défini dans le chapitre précédent $front->registerPlugin(new My_Controller_Plugin_Auth($acl)) ;
Simple comme bonjour ! Non ? 
Je vous propose encore un petit schéma pour améliorer la compréhension du processus.
My_Auth_Adapter
Je pense qu'il est inutile que je répète la documentation qu'on peut trouver sur le site Zend. En gros, elle répond à la question "Comment vérifier le login et mot de passe d'un utilisateur ?". Votre tâche consiste ici en la création de votre propre adaptateur d'authentification ou alors l'utilisation d'un adaptateur existant.
Pour résumer, cette classe est appelée dans une action "login" et elle sauve dans la session (ou ailleurs) l'autorisation d'accès. Je vous conseille vivement d'ajouter dans votre table d'utilisateurs une colonne "role" qui correspondra à un des rôles que nous avons défini précédemment (guest, member ou admin).
My_View_Helper_IsAllowed
Cette aide de vue (Zend_View_Helper_Abstract) permet simplement d'appeler une fonction isAllowed('controller', 'action') avec en premier paramètre le contrôleur et en second l'action sur laquelle on désire effectuer le contrôle de permission.
Vous aurez certainement besoin de cette fonction, par exemple, pour faire apparaître les bons liens sur votre site, en fonction des droits de l'utilisateur.
/**
* Proxy vers le contrôleur d'authentification
**/
class My_View_Helper_IsAllowed extends Zend_View_Helper_Abstract {
protected $_acl;
protected $_auth;
/**
* Proxy vers la fonction acl is allowed function
*/
public function isAllowed($resource, $actions) {
$this->_acl = Zend_Registry::get('acl') ;
$this->_auth = Zend_Auth::getInstance() ;
// contrôle si l'utilisateur est authentifié
if ($this->_auth->hasIdentity()) {
// yes ! on récupère son role
$user = $this->_auth->getStorage()->read() ;
$role = $user['role'] ;
} else {
// non = invité
$role = 'guest';
}
// contrôle si l'utilisateur est autorisé
return $this->_acl->isAllowed($role, $resource, $actions) ;
}
}
Il est possible de définir d'autres aides de vue tout autant utiles. Celle-ci n'est qu'un exemple. Je pense qu'on peut dire qu'à partir du moment où dans un script de vue, on instancie une classe ou une variable du registre, il faut faire une aide de vue.
Conclusion
Voici donc tous les composants réunis pour gérer les accès dans votre site de manière simple et propre. Bien entendu, comme toujours, je vous propose cet article à titre d'inspiration. Le code ci-dessus ne fait pas tout. Par exemple, il ne gère pas les applications multi-modules, ou la définition des ACL est strictement limitée à un fichier INI.
J'espère toutefois avoir réuni en une page tout ce qu'il faut savoir pour gérer correctement les accès sur un site. Si vous avez des questions, n'hésitez pas...
Mis à jour le 4 février 09 pour ajouter la gestion des modules.





Fil des commentaires de ce billet
Commentaires
Bonjour
J'ai implémenté votre exemple qui marche bien après quelques petites corrections. Merci beaucoup.
Cependant j'ai un petit problème.
Ma page est constituée en appelant chaque fois plusieurs controllers (avec actionToStack):
un controller qui geèe l'affichage du menu, un qui affiche la boite de login, un qui affiche la meteo et le controller principal appelle.
Quand je suis sur la page d'accueil en tant que Guest, tout s'affiche bien. Par contre si je vais une une page que Guest n'a pas le droit de voir, je suis bien redirigé vers la page d'index mais dans ce cas, les controllers complementaires (menu, login, meteo) sont refusés, ne s'affichent donc pas et du coup ma page index s'affiche 4 fois. J'ai mis des traces, et dans le pluggin d'authentification je vois que c'est toujours le nom du controller principal qui est reçu et non pas les noms des controller secondaires (menu,...) qui sont reçus donc evalués.
Comment puis-je corriger cela ?
Est ce que je pourrais plutot que de modifier la request en cas d'erreur, carremment faire un vrai redirect (qui aurait comment avantage de bien remettre l'utilsiateur sur la page d'accueil du site (adresse dans la barre d'adresse du navigateur) ? Si oui comment ?
Merci beaucoup pour votre aide et pour cet excelent tuto !
Nathalie
Bonjour Nathalie,
Merci pour votre commentaire.
Si vous désirez interrompre le dispatching et rediriger votre requête sur une autre page, vous pouvez essayer avec la méthode setRedirect de l'object Response :
$response = $front->getResponse();
$response->setRedirect('/' . $controllerName . '/' . $actionName);
$response->sendHeaders();
exit;
Bon code et bonne soirée !
Bonjour et merci pour ce tuto mais j'ai un petit probleme.
$acl = new My_Acl_Ini($config) ;
J'obtiens ceci
Fatal error: Uncaught exception 'Zend_Acl_Exception' with message 'Resource 'login' not found' in C:\wamp\ZendFramework-1.7.2\library\Zend\Acl.php:297 Stack trace: #0 C:\wamp\ZendFramework-1.7.2\library\Zend\Acl.php(574): Zend_Acl->get('login') #1 C:\wamp\ZendFramework-1.7.2\library\Zend\Acl.php(453): Zend_Acl->setRule('OP_ADD', 'TYPE_DENY', 'member', 'login', NULL, NULL) #2 C:\wamp\www\zend_auth\library\My\Acl\Ini.php(57): Zend_Acl->deny('member', 'login', NULL) #3 C:\wamp\www\zend_auth\library\My\Acl\Ini.php(16): My_Acl_Ini->_setPrivileges('member', Object(Zend_Config_Ini)) #4 C:\wamp\www\zend_auth\application\bootstrap.php(28): My_Acl_Ini->__construct('../application/...') #5 C:\wamp\www\zend_auth\public\index.php(8): require('C:\wamp\www\zen...') #6 {main} thrown in C:\wamp\ZendFramework-1.7.2\library\Zend\Acl.php on line 297
(je précise que le chemin vers mon .ini est correct)
Avec vous une idée?
Merci
Je ne reproduis pas cette erreur après quelques tests. L'erreur signifie que vous n'avez pas déclaré la ressource "login". Pourriez-vous vérifier votre fichier config.ini ?
Egalement, vous pouvez vérifier les ressources déclarées en traçant la variable $this->_resources.
Merci.
J'ai tout repris depuis le début.
Dès le début ça foire.
Quand je cré mon objet $acl de la classe My_Acl_Ini j'obtiens un jolie Fatal error: Uncaught exception 'Zend_Config_Exception' with message 'Object of class Zend_Config_Ini could not be converted to string Object of class Zend_Config_Ini to string conversion parse_ini_file(Object) [<a href='function.parse-ini-file'>function.parse-ini-file</a>]: failed to open stream: No such file or directory' in C:\wamp\ZendFramework-1.7.2\library\Zend\Config\Ini.php:117 Stack trace: #0 C:\wamp\www\zend_acl\library\My\Acl\Ini.php(8): Zend_Config_Ini->__construct(Object(Zend_Config_Ini), 'roles') #1 C:\wamp\www\zend_acl\application\bootstrap.php(18): My_Acl_Ini->__construct(Object(Zend_Config_Ini)) #2 C:\wamp\www\zend_acl\public\index.php(8): require('C:\wamp\www\zen...') #3 {main} thrown in C:\wamp\ZendFramework-1.7.2\library\Zend\Config\Ini.php on line 117
Et je ne comprends pas a quoi peux être du cette erreur?
$acl_ini = '../application/acl.ini' ;
$config = new Zend_Config_Ini($acl_ini) ;
$acl = new My_Acl_Ini($config) ;
J'ai bien mon fichier acl.ini dans application et ma classe Ini.php est bien dans library/My/Acl/Ini.php et mon include path.
set_include_path('.' . PATH_SEPARATOR . '../library' . PATH_SEPARATOR . '../application/default/models/' . PATH_SEPARATOR . get_include_path());
Je ne vois pas pourquoi ce problème.
Merci par avance.
Comme ceci, ça ira mieux :
$acl_ini = '../application/acl.ini' ;
$acl = new My_Acl_Ini($acl_ini) ;
My_Acl_Ini telle que je l'ai écrite prend en paramètre un string représentant un chemin vers le fichier INI et non pas un objet Zend_Config_Ini.
Vous pouvez par contre aisément ajouter un contrôle dans la méthode __construct(...) de type :
if ($file instanceof Zend_Config_Ini)
{
...
} else {
...
}
Erci, vous avez pas un petit script fonctionnel avec un formulaire d'authentification avec recup des infos dans la bdd + gestion des rôles?
Merci sinon tant pis
Malheureusement, je n'ai pas un tel script à partager.
Fantastic! Thank you. My written French isn't too good so I have to write this in English
Bonjour, super tuto mais je bloque sur les droits d'accès à ma base de données Access.
Savez vous comment faire pour définir les droits dans ma base de donnés ?
Bonjour Guiseb,
Merci pour votre commentaire.
Je ne suis pas certain de comprendre votre question dans le bon sens.
Si vous désirez gérer les accès à votre application grâce à des données situées dans votre base Access, alors il faut créer une nouvelle classe (par ex. : My_Acl_Db) qui récupère votre configuration stockée dans une ou plusieurs tables.
Si vous cherchez à gérer les droits d'accès à votre base de données, je ne connais pas Access, mais il est fort probable que Zend_Acl ne vous servent à rien pour ça. Les SGBD proposent généralement une gestion de droits propre qui sort totalement du sujet du présent article.
Merci pour cette réponse !
Oui je pense comme vous qu'il est possible de gérer les accès via la BDD mais ces directives sont imposé par mon prof.
Et je ne vois pas comment définir la table qui contiendra les accès puis ensuite créer une classe pour récupérer la config.
Cette partie de la gestion des accès est très flou pour moi étant qu'en deuxième année de BTS informatique.
Bonjour et dabors merci pour ce tuto.
J'ai un problème car la gestion des accès ne fonctionne pas, sans être loguer, en guest donc je peut par exemple accèder au contrôleur admin, voici moin fichier ini:
[roles]
guest = null
member = guest
admin = member
[ressources]
index = null
auth = null
admin = null
[guest]
allow.auth = null
allow.index = null
[member]
deny.auth = null
[admin]
allow.admin = null
désolé, erreur de ma part , j'avais fait
$frontController->dispatch();
avant:
$frontController->registerPlugin(new My_Controller_Plugin_Auth($acl)) ;
, par contre j'ai remplacé dans le plugin My_Controller_Plugin_Auth :
if (!$this->_auth->isIdentified()) {
$role = 'guest' ;
} else {
....
par
if (!$this->_auth->hasIdentity()) {
$role = 'guest' ;
} else {
...
car "Call to undefined method Zend_Auth::isIdentified()"
j'ai toutefois un problème avec ce code:
if (!$this->_acl->isAllowed($role, $this->_request->controller) && is_null($request->getParam('error_handler'))) { $this->getResponse()->clearAllHeaders();
$request->setModuleName(self::FAIL_ACL_MODULE)
->setControllerName(self::FAIL_ACL_CONTROLLER)
->setActionName(self::FAIL_ACL_ACTION);
} else if (is_null($this->_request->getParam('error_handler'))) { $request->setModuleName(self::FAIL_AUTH_MODULE) ->setControllerName(self::FAIL_AUTH_CONTROLLER)
->setActionName(self::FAIL_AUTH_ACTION)
->setDispatched(true);
}
toutes mes pages me redirige vers le controleur que j'ai spécifié dans const FAIL_AUTH_ACTION
si dans la deuxieme partie au niveau du elsse if je met
} else if (!is_null($this->_request->getParam('error_handler'))) { .... }
Les droits au niveau des controleurs fonctionne nikel mais pas les droits sur les actions
quelqu'un peut m'aider ?
Bonjour dev21,
Merci pour la petite correction. Effectivement, la fonction correcte est hasIdentity().
Je vais proposer une version révisée du plugin car je me rends compte que pas mal de choses ont évolué depuis.
ce serait super ! je l'attends avec impatience , merci
Voilà, nouvelle version avec gestion des modules...
J'espère que je n'ai pas laissé trop de bugs !
Bonjour,
Merci pour ce tuto et cette classe qui me réconcilie avec Zend_Acl. Par contre cela me retourne une erreur :
Fatal error: Cannot use object of type stdClass as array in G:\Documents\Programmation\projet\library\My\Controller\Plugin\Auth.php on line 51
la ligne 51 correspond à $role = $user['role'] ;
J'ai peut être oublié de déclarer quelque chose dans mon acl.ini ?
Ha mais bien sûr, j'ai pas encore ajouté dans mon login la gestion des droits !
Bonjours,
j'ai essayé de réaliser ce tutoriel mais j'ai une erreur , il ne trouve pas la class My_ACL_ini , cette class n'est pas publier ici
merci
j'ai finalement trouvé mais j'ai deux autres problèmes
1) j'ai une exception qui me dit que la ressources member,admin.. ne sont pas trouvé or que c'est rôle.
2) j'ai une autre exception
Fatal error: Cannot use object of type stdClass as array in C:\wamp\www\gest-cieptalcars\Application\controllers\plugins\AuthPlugins.php on line 51
voici le bloc d'instruction à la ligne 51
foreach ($ressources as $ressource => $actions) {
if (empty($actions)) {
$actions = null ;
} else {
$actions = explode(',', $actions) ;
}
a+.
j'ai finalement trouvé mais j'ai deux autres problèmes
1) j'ai une exception qui me dit que la ressources member,admin.. ne sont pas trouvé or que c'est rôle.
2) j'ai une autre exception
Fatal error: Cannot use object of type stdClass as array in C:\wamp\www\gest-cieptalcars\Application\controllers\plugins\AuthPlugins.php on line 51
voici le bloc d'instruction à la ligne 51
foreach ($ressources as $ressource => $actions) {
if (empty($actions)) {
$actions = null ;
} else {
$actions = explode(',', $actions) ;
}
a+.
Bonjour,
J'ai un petit problème avec cette classe et les requêtes ajax.
j'ai bien mis dans mon fichier acl.ini :
[roles]
guest = null
member = null
admin = null
[ressources]
index = null
ajax = null
[guest]
allow.index = index
allow.ajax = null
[member : guest]
allow.index = index,contact
allow.ajax = null
[admin : member]
allow.index = index,contact,admin
allow.ajax = null
Lorsque je ne suis pas logué, aucun problème avec mes requêtes ajax mais dès que je suis logué, je vois erreur 403 via firebug et si je change de page je suis délogué.
une idée de la source du problème ?
Merci
Je me permet de relancer ma question.
Dès que je suis loggué et que je fais une requête ajax j'ai erreur 403 forbidden dans Firebug et je suis délogué. Je n'arrive pas à corriger cette erreur.
Une idée ? merci
Erreur 403 Forbidden est une erreur provenant du serveur web qui signifie que le fichier qu'on tente d'appeler n'est pas disponible pour le user Apache.
Un problème de droit sur le fichier appelé ? Que fait ton application en + lorsque tu es identifié ? Est-ce qu'il n'écrirait pas dans un fichier interdit ? Ou tenterait d'accéder à un répertoire interdit ?
Je n'ai jamais rencontré ce problème et je fais énormément d'Ajax en utilisant cette classe.
Merci de me répondre.
Ma requête ajax récupère une liste de données via la BDD et echo le résultat, vraiment classique.
Ce que je ne comprend pas c'est pourquoi quand je ne suis pas logué cela marche sans problème et quand je suis logué j'ai erreur 403 et cela me délogue automatiquement.
Dans le js (via jquery), voilà le type d'url que j'appelle :
url: 'ajax/topthemes/format/html'
J'ai essayé de supprimer le ajaxcontext, renommer le fichier .phtml et d'appeler directement la page par son url. Je n'ai aucun problème que je soit logué ou pas.
J'ai comparé les deux en tête HTML entre quand je suis logué ou pas la seule différence est l'apparition de ces deux lignes en plus :
Set-Cookie
egame_session=deleted; expires=Wed, 05-Mar-2008 11:11:33 GMT; path=/
Serait-il possible qu'au moment de ma requête ajax cela détruise ma session et donc pause problème ?
Oui, JQuery pourrait à la limite détruire le Cookie qui te lie à ta session. L'identifiant de ta session étant stocké sur ta machine. Mais ça ne devrait pas te générer une 403 pour autant...
Tu as essayé de te passer de JQuery et de faire un appel en Javascript "pur" ?
Visiblement, le problème n'est pas du côté de ton code serveur étant donné que le script fonctionne bien si tu l'appelles en direct.
Faire une requête ajax en me passant de jquery ? aille je vais m'arracher les cheveux avec XMLHttpRequest, oké je vais tester.
je viens de tester, la session n'est pas perdue. Donc il s'agirait d'un problème lié à Jquery ? je vais creuser cette piste, merci.
j'ai fait un test en remplaçant url: 'ajax/topthemes/format/html', par url: 'ajax.php' et en mettant un simple echo cela marche sans problème.
Le problème ne vient donc pas de jquery. Comment fais tu pour appeler ton controleur ajax et la méthode voulue ?
J'ai retourné le problème dans tous les sens et la seule explication valable que je vois c'est que lors de ma requête ajax, il y a un problème d'ACL, je n'ai donc pas accès à mon action et cela me renvoit 403.
Pourtant j'ai testé d'appeler l'action directe sans passer par l'ajax et là je n'ai pas de problème de droits.
Je sais que les ACL sont générés en preDispatch grâce à ta classe. Si j'ai bien suivi, tu actives l'accès selon le couple module, controleur, action. Mais lorsque je fais une requête ajax, je ne passe pas par le preDispatch et les droits ne sont pas activés ?
J'ai (enfin) résolu mon problème ça vient de mon plugin qui contrôle si il n'y a pas eu vol de la session.
Désolé d'avoir spammer les commentaires, tu peux les supprimer.
Merci
Pourrais-tu indiquer ce que tu faisais et comment tu l'as corrigé, comme ça ça sera utile pour les suivants.
Merci
J'ai eu le même problème, en utilisant le plugin contre le vol de session de l'appli ZfBook.
La seule solution que j'ai eu pour le moment est de simplement désactiver ce plugin, ce qui est dommage.
Quelqu'un a t'il une solution pour utiliser ce plugin malgré tout, et le désactiver en cas d'appel Ajax ?
merci
j'ai une erreur :
Fatal error: Cannot use object of type stdClass as array in C:\Program Files\EasyPHP 3.0\www\Farkess\core\modules\search\controllers\MyControllerPluginAuth.php on line 54
voici le contenu de la ligne 54:
$rolll = $user['f_user_role'] ;
et voila le code de mon auth adapter :
$db = Zend_Registry::get('publicdb');
$authAdapter = new Zend_Auth_Adapter_DbTable($db);
$authAdapter->setTableName('f_user');
$authAdapter->setIdentityColumn('f_user_login');
$authAdapter->setCredentialColumn('f_user_pw');
// Set the input credential values to authenticate against
$authAdapter->setIdentity($username);
$authAdapter->setCredential($password);
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// success: store database row to auth's storage
// system. (Not the password though!)
$data = $authAdapter->getResultRowObject(null,'f_user_pw');
$auth->getStorage()->write($data);
$this->_redirect('/');
} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
une aide sera le bien venu
merci
Bonjour,
je me suis mis il y a peu à Zend Framework.
Je recherché une solution 'intelligente' pour gérer mes ACL, ce tutoriel, en plus de répondre à mes attentes, m'a permis de mieux comprendre certains points... Merci!
Cependant, je rencontre exactement le même problème que libertux. L'erreur survient lors de la récupération du rôle (pour ma part stocké en DB). J'ai bien effectué la modification des noms de champs pour correspondre au schéma de ma DB.
J'ai fait pas mal d'essais et de modifications, mais pas (encore) trouvé de solution....
Si vous pouviez me renseigner ?
Merci!
Bonjour,
Merci pour vos commentaires.
L'erreur citée signifie que vous tentez probablement d'accéder à une occurrence dans un tableau alors que votre variable est une classe.
A la ligne 54 :
$role = $user['role'] ;
Si $user est une classe alors cette erreur sera renvoyée. Il faut utiliser $user->role à la place ou $user->toArray() si cette méthode existe.
J'espère que ceci résoudra vos problèmes.
Bonjour,
c'était bien ça! Merci !
Néanmoins, les ACL's qui devraient s'appliquer lors de l'authentification ne sont pas appliquées.
Les modules et autres controlleurs qui sont inaccessibles en 'guest' le sont toujours lorsque je suis logué avec un utilisateur ayant le rôle 'admin'...
Je vais étudier mon fichier d'acl plus attentivement, je suppose que c'est de là que provient le problème...
Merci!
Bonjour,
comme indiqué dans mon précédent post, mes droits d'accès après authentification ne sont pas appliqués.
Après plusieurs modifications/tests, je n'ai toujours pas réussi à corriger mon problème.
mon fichier acl.ini contient:
[roles]
guest = null
admin = null
[ressources]
;default module
index = null
login = null
test = null
; admin module
admin_index = null
[guest]
allow.index = null
allow.login = null
deny.test = null
deny.admin_index = null
[admin : guest]
allow.test = null
allow.admin_index = null
Si j'ai bien compris, avec cette configuration, quand un utilisateur obtient le rôle 'admin', il peu accéder au controler 'test' du module 'default' et au controler 'index' du module 'admin' ?
Je ne vois pas d'où pourrait prevenir mon errreur...
Merci.
Simplement du fait que Admin va hériter des droits de Guest donc de deny.test et deny.admin_index.
Par défaut, aucun contrôleur n'est accessible. Il n'est donc pas utile d'ajouter ces deux contrôleurs dans les privilèges de Guest.
En effet, en supprimant ça fonctionne.
Je dois mal comprendre la doc de Zend, je vais la relire.
Merci beaucoup !
Merci pour ce tuto
j'ai trouvé un problème c'est un message d'erreur " Invalid argument supplied for foreach() in C:\EasyPHP 2.0b1\www\TRDGroup\library\My\Acl\Ini.php on line 50"
la ligne 50 correspond à
foreach ($ressources as $ressource => $actions)
dans le fichier My_Acl_Ini qui se trouve ci-dessus
merci d'avance
Merci pour ce SUPPPERRR tuto, mais peut on avoir un exemple a télécharger pour évidement bien assimiler ces notions car (par exemple), tout les tuto de ce genre parle de fichiers "Myaclini.php,..." mais ou les crée, et pour une hiérarchie multi modules comment les implémenté...
merci
Effectivement, je n'explique pas l'emplacement de tous les fichiers car ce tuto couvre un sujet précis. Il existe d'autres tutoriaux qui couvrent les besoins de compréhension des sujets comme l'arborescence ou l'emplacement des fichiers de configuration :
http://www.wowww.ch/index.php?post/...
http://www.wowww.ch/index.php?post/...
Il est également important de ne pas copier coller le code sans comprendre son fonctionnement. Le but étant de proposer un exemple de solution possible mais pas forcément LA solution à votre problème.
Le code de My_Acl_Ini.php proposé ici est utilisable dans une application modulaire. Son emplacement est préconisé dans /library/My/Acl/Ini.php et est chargé grâce au Zend Loader :
http://www.wowww.ch/index.php?post/...
Merci beaucoup !!
Très bon tutorial qui m'a permis de régler le soucis des Acl en moins d'une demi-journée : Je suis content !
Par contre la couleur de police blanche sur un fond noir, ça pique un peu les yeux ...
Tiens je vais visiter le site en entier pour voir ce qu'il y a d'autres
merci pour ce topic, mais faut que les mentalites change!
Merci !
une bonne idee merci, bonne continuation
Bonjour,
Merci pour ce tuto, mais j'ai une erreur "My_ACL_ini" not found.
en fait la classe My_ACL_ini ce trouve ou .
Attention à la casse (majuscules/minuscules) c'est My_Acl_Ini.
La classe est décrite dans le chapitre "My_Acl" et le code source téléchargeable à la fin du chapitre.
j'ai toujours la meme erreur, malgré que j'ai la classe, et j'ai reverifie le chemin et tout.
est ce un probleme d'arborescence "C:\wamp\www\SamaxSoft\application\models\My_Acl_Ini" ? ou toute les classes de votre exemple doivent etre dans le meme repertoire ?
A cet emplacement, ça ne fonctionnera pas.
A lire de toute urgence :
http://www.wowww.ch/index.php?post/...
Bonjour,
j'ai bien lu le lien et c'est plus claire maintenant, mais il reste un probleme que je ne comprend pas. j'ai mon Plugin_AuthControlle dans "C:\.....\controller\Plugin\AuthController" et a l'excution j'ai cette erreur, "Fatal error: Class 'Plugin_AuthController' not found in C:\wamp\www\SamaxSoft\index.php on line 46" avec deux warning ou il est noter ..."Failed opening 'Plugin\AuthController.php' for inclusion (include_path='.;./library;./application/models/;.;C:\php5\pear') in C:\wamp\www\SamaxSoft\library\Zend\Loader.php on line 83", et quand je copier mon controller Plugin_AuthControlle dans "C:\.....\models\Plugin\AuthControlle" j'ai une autre erreur "Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (account)' in C:\wamp\www\SamaxSoft\library\Zend\Controller\Dispatcher\Standard.php:241 Stack trace: #0 C:\wamp\www\SamaxSoft\library\Zend\Controller\Front.php(934): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #1 C:\wamp\www\SamaxSoft\index.php(57): Zend_Controller_Front->dispatch() #2 {main} thrown in C:\wamp\www\SamaxSoft\library\Zend\Controller\Dispatcher\Standard.php on line 241" car dans mon bootstrap je definis le chemin des controller ici "$frontController->setControllerDirectory('./application/controllers');". si vous avez une idee de quoi s'agit il ; Merci
Il faut absolument comprendre le fonctionnement du contrôleur et la différence entre un contrôleur et une classe modèle sinon rien ne sera jamais simple.
Visiblement, vous confondez ces différents éléments et du coup, rien ne fonctionne. Un plugin n'est pas un contrôleur, un contrôleur n'est pas une classe modèle et une classe modèle ne peut pas être nommée comme un contrôleur.
Je vous conseille encore la lecture de ces articles :
http://www.wowww.ch/index.php?post/...
http://www.wowww.ch/index.php?post/...
Bonne chance !
Bon j'ai laisser tomber, je l'ai fait avec l'arborescence que vous avez propose.
Merci et bonne continuation.
Un blog est un journal personnel en effet mais surtout un lieu dechange et de partage d idees (tout comme je fais actuellement sur le sujet) Bref, Merci pour les tuyaux, cest tres enrichissant.
Bonjour,
très bon tutorial sur les ACL. J'ai voulu mettre en pratique votre solution, mais je rencontre une erreur bizarre :
resource '
si quelqu'un a une idée. C'est au moment d'attribuer les privilèges, par l'intermédiaire de la fonction $this->{$do}($role, $ressource, $actions);
Merci
Quand je fais un echo du rôle, de la resource et des privilèges, j'obtiens ceci dans le navigateur
guest�*�_allowModifications
Merci pour cet excellent tutorial.
Je rencontre pourtant une difficulté :
- je teste l'accès à module/controlleur/action = admin/index/index
- le plugin s'exécute
- l'autorisation Zend_Auth est valide
- le controle des ACL échoue (normal, je n'avais pas le droit)
=> je redirige donc vers module/controlleur/action = public/index/index
Or, je me retrouve en admin/index/index !!!
C'est comme si le _redirect effectué était écrasé.
J'ai vérifié que je n'ai aucun post"quelquechose" qui s'exécute après.
Le fait de "fermer" les scripts php par "?>" peut-il etre une cause ?
Auriez-vous des idées / pistes à me proposer ?
Merci par avance,
Jean
PS : voici le dump de $request effectué en fin de plugin
object(Zend_Controller_Request_Http)#77 (14) {
["_paramSources:protected"] => array(2) {
[0] => string(4) "_GET"
[1] => string(5) "_POST"
}
["_requestUri:protected"] => string(12) "/admin/index"
["_baseUrl:protected"] => string(0) ""
["_basePath:protected"] => NULL
["_pathInfo:protected"] => string(12) "/admin/index"
["_params:protected"] => array(3) {
["module"] => string(5) "admin"
["controller"] => string(5) "index"
["action"] => string(5) "index"
}
["_aliases:protected"] => array(0) {
}
["_dispatched:protected"] => bool(true)
["_module:protected"] => string(6) "public"
["_moduleKey:protected"] => string(6) "module"
["_controller:protected"] => string(5) "index"
["_controllerKey:protected"] => string(10) "controller"
["_action:protected"] => string(5) "index"
["_actionKey:protected"] => string(6) "action"
}
Ouppps !!!
je me suis fait avoir :
le controler demandé : admin/index/index reste affiché dans l'URL
alors que la requête a bien été redirigée vers public/index/index
Merci encore pour cette superbe classe qui permet de gérer ses ACL dans un .ini !
Jean
Merci pour ce Très Bon tuto, il m'a bien aidé. Par contre j'ai modifié un peu le fonctionnement avec l'auth. Mais rien de bien méchant...
Sinon je fais aussi quelque tutos sur le Zf, n'hesites pas a venir faire un tours
http://blog.lyrixx.info/zend-framew...
Merci beaucoup pour ce tuto, il m'a bien aidé a pigé le fonctionnement .
J'ai cependant un problème, et j'espère que vous pourrez m'aider, j'ai malheureusement l'erreur suivante :
Catchable fatal error: Object of class Zend_Config could not be converted to string in C:\wamp\www\zendtest\library\My\Acl\Ini.php on line 40
Quand on regarde, cela correspond a la fonction _SetRoles .
merci d'avance.
Cordialement,
C'est l'un de mes préférés post, je vais ajouter cette page à ma liste de favoris. et je vais revenir à votre blog