Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour à tous,
Je débute totalement sous ZF, mais j'ai déjà pas mal bossé sur des frameworks J2EE, donc ca va j'avance assez vite mais j'ai besoin de vos conseils pour mon architecture en modules et la gestion des droits.
Voici le contexte :
Dans mon appli j'aurais plusieurs niveau d'utilisateurs, j'ai donc les modules suivants :
Default (dans lequel je met le controleur de l'authentification, celui des erreurs, etc.)
Niveau1 (contient les controlleurs et actions de niveau1)
Niveau2 (contient les controlleurs et actions de niveau2)
...
La capture d'écran ci-dessous vous montre mon architecture physique de fichiers que j'ai constituée petit à petit en suivant les différents tutos disponibles sur le net.
A ce stade j'ai implémenté l'authentification via Zend_Auth et une base MySQL, et maintenant je voudrais utiliser les ACL pour définir les droits de chaque utilisateur.
J'ai essayé de mettre en oeuvre les tutos sur les ACL mais j'ai une question :
D'après ce que j'ai compris, dans les tutos on déclare des ressources, que l'on pourrait nommer comme on veut, exemple je déclare la ressource "toto", je dit que "guest" peut y accéder et ensuite c'est à moi de voir dans mes controlleurs si la personne qui demande l'action est bien "guest" et si il a le droit "toto".
Hors ce que j'aurais aimé, c'est définir des droits en fonction du nom de mes modules/controlleurs/actions.
C'est à dire pouvoir dire que le rôle "guest" permet d'accéder à HOST/niveau1/caisseauto/afficher, et que le rôle "gestionnaire1" permet d'accéder à HOST/niveau1/caisseauto/saisir.
Le tout sans rien rajouter dans mes différents contrôleurs...
J'espère avoir été assez clair et merci d'avance pour vos conseils.
Dernière modification par vallica (29-10-2007 11:25:20)
Hors ligne
Bonjour,
Tu as un exemple un peu plus complet dans le tuto suivant : http://devzone.zend.com/node/view/id/1665 .
Dans ce tutoriel, les tests de droits se font dans un plugin (en fonction du controller de de l'action appelée. Tu peux l'adapter pour ajouter les modules) et non dans les actions.
A+, Philippe
Hors ligne
OK merci à tous les deux, je commence la lecture
Hors ligne
C'est encore moi, j'ai un souci avec le code du tuto qui semble "perimé" d'après les commentaires.
J'obtiens l'erreur
Fatal error: Can not call constructor in F:\www\zend\index.php on line 36
lorsque j'utilise ce bootstrap :
<?php error_reporting(E_ALL|E_STRICT); date_default_timezone_set('Europe/Paris'); include "Zend/Loader.php"; Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Config_Ini'); Zend_Loader::loadClass('Zend_Registry'); Zend_Loader::loadClass('Zend_Db'); Zend_Loader::loadClass('Zend_Db_Table'); // auth Zend_Loader::loadClass("Zend_Auth"); Zend_Loader::loadClass("Zend_Auth_Result"); Zend_Loader::loadClass("Zend_Auth_Adapter_Interface"); Zend_Loader::loadClass("Zend_Acl"); // Chargement du fichier ini de config $config = new Zend_Config_Ini('./application/config.ini', 'general'); $registry = Zend_Registry::getInstance(); $registry->set('config', $config); // setup database $db = Zend_Db::factory($config->db->adapter, $config->db->config->toArray()); Zend_Db_Table::setDefaultAdapter($db); Zend_Registry::set('dbAdapter', $db); // Create auth object $auth = Zend_Auth::getInstance(); // Create acl object class MyAcl extends Zend_Acl { public function __construct(Zend_Auth $auth) { parent::__construct(); $this->add(new Zend_Acl_Resource('niveau1')); $this->add(new Zend_Acl_Resource('niveau2')); // le rôle superviseur aura accès au module nommé Niveau1 $this->addRole(new Zend_Acl_Role('superviseur')); $this->allow('superviseur', 'niveau1'); // le rôle coordinateur aura accès au module nommé Niveau2 $this->addRole(new Zend_Acl_Role('coordinateur')); $this->allow('coordinateur', 'niveau2'); // le rôle admin donne accès à tout $this->addRole(new Zend_Acl_Role('admin')); $this->allow('admin'); } } $acl = new MyAcl($auth); // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->throwExceptions(true); $frontController->setControllerDirectory(array( 'default' => 'application/modules/default/controllers', 'niveau1' => 'application/modules/Niveau1/controllers' )); //$frontController->addModuleDirectory('application/modules'); // run! $frontController->dispatch();
La ligne en question c'est
$acl = new MyAcl($auth);
, et un commentaire nous dit
Howdy folks,
Just wanted to post to let everyone know that calling parent::__construct() on a class that extends Zend_Acl will result in fatal error because Zend_Acl does not have a constructor.
So, for those of you following this old article verbatim, beware that much has changed for both Zend_Auth and Zend_Acl since this writing.
Best regards,
Darby
En gros je crois comprendre que la conception des classes Auth et Acl a été fortement modifiée ce qui l'article obsolète...
Auriez-vous une idée de ce qui a changé ? je suis désolé d'être aussi insistant mais la documentation ne m'aide pas beaucoup sur mon approche en modules.
Merci d'avance.
Hors ligne
Effectivement, le code à utiliser est un peu différent.
Voici des fichiers modifiés (basé sur l'exemple de devzone.zend.com) qui fonctionnent sur un de mes projet:
index.php:
<?php /** * * * * */ // pour le developpement error_reporting(E_ALL|E_STRICT); // chemin vers racine du site define('SITE_PATH', './'); // chemin vers moteur application define('LIB_PATH', './application/'); // la date date_default_timezone_set('Europe/Paris'); // les includes de base set_include_path( LIB_PATH . PATH_SEPARATOR . LIB_PATH . 'lib/ZF' . PATH_SEPARATOR . LIB_PATH . 'lib/ZF/library' //. PATH_SEPARATOR . LIB_PATH . 'lib/ZF/incubator/library' . PATH_SEPARATOR . LIB_PATH . 'lib/Neni' . PATH_SEPARATOR . LIB_PATH . 'models' . PATH_SEPARATOR . get_include_path() ); // A METTRE AILLEURS : FONCTIONS POUR CONVERTIR function ConvertJSDateToMysql($txt){ $tmp = explode('/',$txt); if( (isset($tmp[2]))&&(isset($tmp[1]))&&(isset($tmp[0])) ){ return $tmp[2].'-'.$tmp[1].'-'.$tmp[0]; }else{ return 'NULL'; } } // init require_once 'Zend/Loader.php'; require_once 'Zend/Registry.php'; // le fichier de configuration require_once 'Zend/Config/Ini.php'; $config = new Zend_Config(new Zend_Config_Ini('./application/config/config.ini', 'test')); // adresse absolue du site define('SITE_URL', $config->weburl); define('SITE_ABS_URL', 'http://'.$config->webhost.$config->weburl); // la BDD require_once 'Zend/Db.php'; require_once 'Zend/Db/Adapter/Pdo/Mysql.php'; $db = Zend_Db::factory($config->database); Zend_Registry::set('db', $db); // identification require_once 'Zend/Auth.php'; $auth = Zend_Auth::getInstance(); require_once 'Zend/Auth/Storage/Session.php'; $auth->setStorage(new Zend_Auth_Storage_Session('leNomQuiVaBien')); Zend_Registry::set('auth', $auth); // les droits de l'application require_once("ModemAcl.php"); $acl = new Modem_Acl($auth); Zend_Registry::set('acl', $acl); // on y va require_once 'Zend/Controller/Front.php'; require_once 'Zend/Controller/Router/Rewrite.php'; require_once 'Neni_PluginAuth.php'; $router = new Zend_Controller_Router_Rewrite; $front = Zend_Controller_Front::getInstance(); $front->setControllerDirectory(LIB_PATH.'bureau/controllers'); $front->throwExceptions(true); $front->addModuleDirectory(LIB_PATH.'modules'); $front->setRouter($router) ->setDispatcher(new Zend_Controller_Dispatcher_Standard()) ->setRouter(new Zend_Controller_Router_Rewrite()) ->registerPlugin(new Neni_PluginAuth($auth, $acl)); $front->dispatch(); ?>
Le plugin de test de l'utilisateur et des droits (en un seul à la différence de l'original):
<?php // verification que session ok // et aussi que droit ok require_once 'Zend/Controller/Plugin/Abstract.php'; class Neni_PluginAuth extends Zend_Controller_Plugin_Abstract { private $_auth; private $_acl; private $_login = array('module' => 'default', 'controller' => 'index', 'action' => 'index'); private $_noauth = array('module' => 'default', 'controller' => 'login', 'action' => 'session'); private $_noagreement = array('module' => 'default', 'controller' => 'login', 'action' => 'privileges'); public function preDispatch(Zend_Controller_Request_Abstract $request) { $this->_auth = Zend_Registry::get('auth'); $this->_acl = Zend_Registry::get('acl'); if ($this->_auth->hasIdentity()) { $role = $this->_auth->getStorage()->read()->role; } else { $role = 'invite'; } $controller = $request->controller; $action = $request->action; $module = $request->module; $resource = $controller; if (!$this->_acl->has($resource)) { $resource = null; } // test session if (!$this->_auth->hasIdentity()) { // test si la première page if(($controller=='index')&&($module=='default')){ $module = $this->_login['module']; $controller = $this->_login['controller']; $action = $this->_login['action']; // si le login }else if(($controller!='login')&&($module!='default')){ $module = $this->_noauth['module']; $controller = $this->_noauth['controller']; $action = $this->_noauth['action']; } }else{ // test droits //$f = fopen('debug.txt','a'); //fwrite($f,"module:". $module."\ncontroller:".$controller."\naction:". $action."\n"); //fwrite($f,'role:'.$role."\nautrisaition:".(($this->_acl->isAllowed($role, $module, /*$controller,*/ $action))?'oui':'non')."\n\n"); //fclose($f); if(!$this->_acl->isAllowed($role, $module, /*$controller,*/ $action)){ $module = $this->_noagreement['module']; $controller = $this->_noagreement['controller']; $action = $this->_noagreement['action']; } } $request->setModuleName($module); $request->setControllerName($controller); $request->setActionName($action); } }
et enfin le contrôleur pour le login:
<?php // // Login sur bureau // require_once 'Zend/Controller/Action.php'; class LoginController extends Zend_Controller_Action { var $db, $auth; public function init() { Zend_Controller_Front::getInstance()->setParam('noViewRenderer', true); $this->db = Zend_Registry::get('db'); $this->auth = Zend_Registry::get('auth'); //$this->getResponse()->setHeader('Content-Type', 'application/x-json'); } public function indexAction() { // verification pas vide if((!isset($_POST['login']))||(!isset($_POST['password']))||($_POST['login']=='')||($_POST['password']=='')) { $data['success'] = false; } else { // regarde si dans la BDD require_once 'Zend/Auth/Adapter/DbTable.php'; $authAdapter = new Zend_Auth_Adapter_DbTable($this->db); $authAdapter->setTableName('bureau_utilisateur') ->setIdentityColumn('pseudo') ->setCredentialColumn('password'); $authAdapter->setIdentity($_POST['login']) ->setCredential($_POST['password']); $result = $this->auth->authenticate($authAdapter); if ($result->isValid()) { $data['success'] = true; // sauvegarde dans session $this->auth->getStorage()->write($authAdapter->getResultRowObject(array('id', 'pseudo', 'nom', 'prenom', 'email', 'role','actif'))); // on envoie le bureau à afficher $data['data']=$this->auth->getStorage()->read(); } else { $data['success'] = false; } } $this->getResponse()->setBody(json_encode($data)); } // si plus d'identité (delai session) public function sessionAction() { $this->getResponse()->setBody('{success:false,initialisation:pbreconnect(),message:"session"}'); } // si pas les privileges public function privilegesAction() { $this->getResponse()->setBody('{success:false,initialisation:pbpasdedroits(),message:"droit"}'); } }
Dans cet exemple, c'est du Json qui sort, mais il n'est pas bien compliqué de faire autre chose.
Vous pouvez trouver les sources de l'application (début d'un bureau en ligne pour la gestion d'une association) ici:
http://www.neni.org/Site_test.tar.bz2
Si vous voulez le tester, il suffit de modifier le fichier /application/config/config.ini (info sur bdd) et de faire la table utilisateur avec le fichier SQL dans /apllication/sql.
Dernière modification par neni (12-11-2007 23:34:32)
Hors ligne
Merci, entre temps j'avais réussi à faire tourner le code mais je vais essayer le tiens prochainement pour peut-être m'en inspirer.
Bon dev
Hors ligne
Bonjour à tous
Désolé de faire remonter ce post, mais j'ai quelques soucis en essayant moi aussi d'adapter mon code à "l'ancien" de Devzone.zend.
J'ai donc fais ma classe MyAcl définissant les ressources et les rôles. J'ai pu tester que cela fonctionnait. Je souhaite maintenant mettre en place le plugin permettant de tester la permission d'afficher ce qui à été demndé en fonction du rôle de l'utilisateur. Et c'est là que ça coince...
Voici un peu de code.
Tout d'abord, le bootstrap :
// Create auth object $auth = Zend_Auth::getInstance(); // Create acl object $acl = new MyAcl($auth); // see .... // setup controller $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new MyPluginAuth($auth, $acl)); $frontController->throwExceptions(true); $frontController->setControllerDirectory('./application/controllers'); // run! $frontController->dispatch();
Ensuite le plugin (il s'agit du même que pour le tuto)
<?php class MyPluginAuth extends Zend_Controller_Plugin_Abstract { private $_auth; private $_acl; private $_noauth = array('module' => 'default', 'controller' => 'login', 'action' => 'index'); private $_noacl = array('module' => 'default', 'controller' => 'error', 'action' => 'privileges'); public function __construct($auth, $acl) { $this->_auth = $auth; $this->_acl = $acl; } public function preDispatch($request) { if ($this->_auth->hasIdentity()) { // Recuperer içi le role de l'utilisateur connecté //$role = $this->_auth->getIdentity()->getUser()->role; $role = 'membre'; } else { $role = 'invite'; } $role = 'invite'; $controller = $request->controller; $action = $request->action; $module = $request->module; $resource = $controller; if (!$this->_acl->has($resource)) { $resource = null; } if (!$this->_acl->isAllowed($role, $resource, $action)) { if (!$this->_auth->hasIdentity()) { $module = $this->_noauth['module']; $controller = $this->_noauth['controller']; $action = $this->_noauth['action']; } else { $module = $this->_noacl['module']; $controller = $this->_noacl['controller']; $action = $this->_noacl['action']; } } $request->setModuleName($module); $request->setControllerName($controller); $request->setActionName($action); } }
Et le problème c'est que tout ça me retourne deux grosses erreurs :
Strict Standards: Declaration of MyPluginAuth::preDispatch() should be compatible with that of Zend_Controller_Plugin_Abstract::preDispatch() in /Applications/MAMP/htdocs/SncfStore/application/lib/MyPluginAuth.php on line 63 Fatal error: Uncaught exception 'Zend_Session_Exception' with message 'Session must be started before any output has been sent to the browser; output started in /Applications/MAMP/htdocs/SncfStore/application/lib/MyPluginAuth.php/63' in /Applications/MAMP/htdocs/library/Zend/Session.php:359 Stack trace: #0 /Applications/MAMP/htdocs/library/Zend/Session/Namespace.php(116): Zend_Session::start(true) #1 /Applications/MAMP/htdocs/library/Zend/Auth/Storage/Session.php(85): Zend_Session_Namespace->__construct('sessionauth') #2 /Applications/MAMP/htdocs/SncfStore/index.php(60): Zend_Auth_Storage_Session->__construct('sessionauth') #3 {main} thrown in /Applications/MAMP/htdocs/library/Zend/Session.php on line 359
J'ai bien cherché mais je ne vois pas comment y remedier... Si vous avez des idées, je suis novice, donc preneur !
Merci d'avance
Guiton
Hors ligne
hello,
il faut utiliser la même déclaration que dans Zend_Controller_Plugin_Abstract , y compris le typage de $request
public function preDispatch(Zend_Controller_Request_Abstract $request)
et là ca marchera sans problème
bonne soirée
Hors ligne
Salut,
Merci de cette réponse julz, j'ai un peu honte d'être passé à côté de ça quand même...
Mais bon, ça fonctionne parfaitement, alors merci !
Bonne journée
Hors ligne