Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Pages: 1
Bonjour,
Je suis de retour sur le forum car je cherche à faire fonctionner Zend_Acl et Zend_Auth, j'ai lu la doc, plusieurs tutos mais je ne comprend toujours pas comment cela fonction. J'ai réussit à mettre en place Zend_Auth avec cette exemple : http://www.z-f.fr/forum/viewtopic.php?id=3332
Et j'aimerais maintenant le gérer via ACL :
ARCHITECTURE :
Application/
bootstrap.php
/config
/controllers
/models
/views
/scripts
/helpers
/layouts
Library/
/My
/Zend
Public/
index.php
.htaccess
/css
/js
CONTRÔLEURS/ACTIONS :
index /
Pages /
/Sport
/Lecture
/Musique
Membre /
/Mesinfos
/Moncompte
/EditCompte
Admin /
/Voir
/Ajouter
/Supprimer
L'idée et de créer 4 rôles : invité || membre || Admin || Full_Admin
Et de gérer les accès :
Invité -> index et pages uniquement
Membre -> +Membre
Admin -> +Admin/voir (Seulement cette action dans le contrôleur admin)
Full_Admin -> All rights
lorsque je fait appel à Zend_Auth, il va chercher dans un table MySql qui comporte les champs suivants :
id # user # pass # role
j'aimerais définir les rôles en fonction des données de la table
Ce que j'ai saisit :
Création d'une class My_Acl_MyAcl extends Zend_Acl
dans : Lib/My/Acl/MyAcl.php
Ensuite un plugin :
class My_Plugin_Auth extends Zend_Controller_Plugin_Abstract
Qui doit, je suppose se trouver dans le dossier Application, sous quelle nom ?
Est ce que le plugin et appelé automatiquement avant chaque contrôleur ?
Comment le implémenter l'acl dans le bootstrap ?
Les exemples et tutos trouvé font tous référence au fichier index.php dans /public ?
Si vous avez un bon tuto ou des exemples, pour la V1.8 je suis preneur car je ne trouve & surtout ne comprend pas trop ?
Dede
Hors ligne
Moi j'ai suivis ce lien : http://codeutopia.net/blog/2009/02/06/z … mple-acls/
Je l'ai modifié de tel sorte que je dispose de 3 rôles : admin, utilisateur, visiteur.
Mon application est découpée en deux modules : front (default), back (admin)
Par défaut, un utilisateur pas authentifié hérite du role visiteur.
Si il y a authentification, alors je regarde l'ID de mon utilisateur :
- Si cet ID correspond à un administrateur, il hérite du rôle admin
- Sinon, il hérite du rôle utilisateur.
avec :
// on récupère le controleur comme ressource
$resource = $request->getModuleName();
// Si le rôle ne dipose pas de la ressource
if(!$this->_acl->isAllowed($role, $resource, 'view')) {
// Alors l'utilisateur est redirigé vers la page d'authentification
$request->setModuleName('default')
->setControllerName('auth')
->setActionName('login');
Par défaut l'utilisateur non authentifié est toujours redirigé sur ma page de login. S'il est authentifié, il peut se balader partout sauf dans le backoffice.
La méthode isAllowed vérifie la cohérence entre le rôle (visiteur, admin utilisateur) et les ressources (les modules admin, default) déclarés dans une classe My_Acl qui étend Zend_Acl (voir tuto).
Bon courage
Hors ligne
Merci
Je vais regarder ce tuto et je reviens pour les questions si ce n'est pas clair
Hors ligne
Mon plus gros soucis reste intact,
avec ce type de fichier /public/index.php
// Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../library'), get_include_path(), ))); /** Zend_Application */ require_once 'Zend/Application.php'; // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap() ->run()
qui lance le fichier /application/Bootstrap.php via application/configs/application.ini :
[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.layout.layoutPath = APPLICATION_PATH "/views/layouts" resources.db.adapter = "PDO_MYSQL" resources.view[] = [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.db.params.host = localhost resources.db.params.dbname = test resources.db.params.username = root resources.db.params.password = root
bootstrap.php :
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initAutoload() { $autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => 'Monapp', 'basePath' => dirname(__FILE__), )); return $autoloader; } protected function _initDoctype() { $this->bootstrap('view'); $view = $this->getResource('view'); $view->doctype('XHTML1_STRICT'); } protected function _initHTMLView() { $this->bootstrap('view'); $view = $this->getResource('view'); $view->headLink()->appendStylesheet('/css/stylesheet.css'); $view->headScript()->appendFile('/js/fonctions.js','text/javascript'); } }
Dans ce cas de figure, chaque fonction du Bootstrap initialise tour à tour l'autoload, le doctype et les vue
mais comment définir le front ou backend contrôleur, function _initFrontController() ?
pour pouvoir ajouter le $frontController->registerPlugin(new My_Plugin_Acl($acl));
J'ai commencer à saisir l'ancienne méthode mais là je bloque ?
Du coup il ne trouve pas le plugin.
Même en faisant appel à ma class acl My_Acl enregistré dans Library/My/Acl.php à partir du controlleur il me retourne une erreur :
Class 'My_Acl' not found in /var/www/application/controllers/IndexController.php
public function indexAction() { //action Index $auth = Zend_Auth::getInstance(); $role ='guest'; if($auth->hasIdentity()){ $rs = $auth->getIdentity(); if($rs->full_admin == 1) $role = 'admin'; $acl = new My_Acl(); if($acl->isAllowed($role, 'news', 'comment')) { echo 'acces'; //pour essayer } } }
Sinon merci pour ce Tuto qui est assez clair, je pense que mon principal problème et la compréhension de fichier .ini et du "nouveau" Bootstrap
Dede
Hors ligne
En fait tu pourrais recenser ton plugin dans application.ini avec
;autoloaderNamespaces[] = "My_"
;resources.frontController.plugins.acl = My_Controller_Plugin_Acl
Mais moi mon plugin récupère un paramètre ($acl) que tu ne peux pas préciser directement dans application.ini
Du coup, je déclare mon plugin dans mon bootstrap :
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initControllersPlugins()
{
$acl = new My_Acl();
$frontController = Zend_Controller_Front::getInstance();
$frontController->registerPlugin(new My_Plugin_Controller_Acl($acl));
}
...
De cette manière mon plugin sera appelé systématiquement.
Hors ligne
Pour ta classe My_Acl non chargée, peux-tu me montrer son code ?
Hors ligne
Je suis en train de devenir chèvre !!
J'ai repris les doc et du coup j'ai fait ca dans le bootstrap :
protected function _initAutoload() { $autoloader = new Zend_Application_Module_Autoloader(array( 'basePath' => dirname(__FILE__), 'namespace' => 'My', )); return $autoloader; }
le code de application/acls/Config.php (Anciennement Acl.php "My_Acl")
class My_Acl_Config extends Zend_Acl { public function __construct() { //Ajout des roles : geust & User hérité de guest $this->addRole(new Zend_Acl_Role('guest')); $this->addRole(new Zend_Acl_Role('user'), 'guest'); //Ajout des ressources : index & page hérité de index $this->add(new Zend_Acl_Resource('index')); $this->add(new Zend_Acl_Resource('news'), 'page'); //Authorisation pour le Guest de voir l'index $this->allow('guest', 'index', 'view'); //Et User de voir page $this->allow('user', 'page', 'comment'); } }
Et j'essaie de l'appeler du contrôleur ou du bootstrap et il me met toujours ça :
Fatal error: Class 'My_Acl_Config' not found in /var/www/application/controllers/IndexController.php on line 23
$acl = new My_Acl_Config();
Hors ligne
Dans quel répertoire se trouve ta classe ?
Peux-tu nous montrer son code ?
Hors ligne
Salut,
J'ai fais ça :
/var/www/
application/
/acls
Config.php
/configs
/controllers
/models
/plugins
Acl.php
/views
/scripts
/layouts
/helpers
Bootstrap.php
library/
/Zend
public/ (root monsite.com)
/js
/css
.htaccess
index.php
La classe "Myacl" qui se nomme My_Acl_Config se trouve dans le repertoire "acls" qui est dans "application" et le code est dans le post précédent (2ème block).
C'est bien celui la que tu veux ?
Et voila le code du plugin situé dans "plugins"
class My_Plugin_Acl extends Zend_Controller_Plugin_Abstract { private $_acl = null; public function __construct(Zend_Acl $acl) { $this->_acl = $acl; } public function preDispatch(Zend_Controller_Request_Abstract $request) { //As in the earlier example, authed users will have the role user $role = (Zend_Auth::getInstance()->hasIdentity()) ? 'user' : 'guest'; //For this example, we will use the controller as the resource: $resource = $request->getControllerName(); if(!$this->_acl->isAllowed($role, $resource, 'view')) { //If the user has no access we send him elsewhere by changing the request $request->setModuleName('auth') ->setControllerName('auth') ->setActionName('login'); } } }
Dede
Dernière modification par Dede (31-07-2009 09:50:33)
Hors ligne
Chez moi la classe My_Acl.php se trouve dans
library
Zend
Date.php
Version.php
(...)
My
Acl.php
Et la nommenclature de la classe c'est "class My_Acl extends Zend_Acl ..."
Il faut respecter les conventions. Avec My_Acl_Config l'autoloader s'attend à :
My/Acl/Config.php
Hors ligne
Salut,
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'basePath' => dirname(__FILE__),
'namespace' => 'My',
));
return $autoloader;
}
Attention ce code n'est pas bon. Déjà il est ambigu, on pourrait confondre ce namespace, qui pour toi est celui du module par défaut, avec un namespace de librairie (après ça fonctionnera quand même hein, libre à toi).
Sinon le préfix déclaré doit contenir l'underscore > My_ et non pas My.
Enfin, si ta classe se trouve dans application/acls/config.php il faut déclarer ce type de resource au frontcontroller qui ne la connait certainement pas par défaut.
$moduleLoader->addResourceType('acl', 'acls', 'Acl'); // type, chemin, namespace
De cette manière il saura ou chercher une classe "My_Acl_".
Je ne sais pas comment tu en es arrivé à donner "My_" comme namespace pour ton application mais je pense que tu finiras par t'embrouiller avec les tuto ou autre discussion à ce sujet
A+ benjamin.
Hors ligne
Réponse à vincent :
Oui, au départ c'est bien ce que j'avais fait mais elle ne se chargeait pas?
Donc, j'ai repris un autre test que j'avais fait (pour Zend_Form) et j'ai vu qu'un appel à partir du contrôleur de ce type :
$form = new My_Form_Users(); faisait appel à un fichier dans "application/forms/Users.php" donc j'ai essayé de cette manière ?
Je ne voit pas pourquoi il ne se charge pas ?
Peut etre à cause de ça dans le fichier .ini :
includePaths.library = APPLICATION_PATH "/../library"
je ne sait pas si il est utile de mettre le / avant ../library puisque le serveur le met ? mais la librairie se charge ?
James a écrit:
Je ne sais pas comment tu en es arrivé à donner "My_" comme namespace pour ton application mais je pense que tu finiras par t'embrouiller avec les tuto ou autre discussion à ce sujet
C'est vrais que selon les tuto ça change, est ce que je devrais laisser 'Default_' ou 'Default' ?
c'est vrai que du coup je ne comprend pas trop car mes modules sont effectivement préfixé 'My_' mais si je fait un appel dans le bootstrap comme ceci :
protected function _initControllersPlugins() { $acl = new My_Acl(); $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new My_Plugin_Controller_Acl($acl)); }
même avec le fichier dans library/My/acl.php ça ne fonctionne pas ?
Dernière modification par Dede (31-07-2009 10:21:12)
Hors ligne
Je pense que tu confonds application, modules et librairie.
Le module par défaut est l'organisation "models/views/controllers" utilisée par défaut par l'application. Par exemple quand tu vas sur l'adresse http://localhost/monsite/ ce sera le module par défaut qui sera utilisé. C'est à dire, l' IndexController du module par défaut et la vue index du module par défaut.
Dans ton cas le module par défaut se trouve dans le dossier "Application". Il n'est pas forcément utile de préfixer les classes de ton module par défaut. Tu peux très bien faire:
protected function _initAutoload() { $autoloader = new Zend_Application_Module_Autoloader(array( 'basePath' => dirname(__FILE__), 'namespace' => '', // <-- aucun namespace )); return $autoloader; }
De mon côté j'ai choisi le namespace "App", mais ce n'est vraiment pas obligatoire.
A côté de ça tu vas avoir une librairie perso (qui n'est pas un module) qui regroupe toutes les surchages du ZF que tu fais et toutes les classes génériques que tu vas utiliser dans tout le projet.
Dans les exemples présents sur le net, tu retrouveras souvent le namespace "My" pour ces classes là.
Elles sont situés dans le dossier "library/" et non pas dans "application/". C'est dans ce dossier que tu stockeras par ex. une classe "My_Acl" qui étend "Zend_Acl", ou encore tes plugins, tes helpers d'action etc. etc.
Pour ça, il faut ajouter le dossier library à l'include_path, déclarer le namespace à Zend_Application:
; application.ini autoloaderNamespaces[] = "My_"
Et surtout respecter les conventions pour tes dossiers. Si ta classe se nomme My_Acl_Config, le "_" représente un nœud dans l'arborescence dans les conventions PEAR/Zend. L'autoloader s'attendra donc à trouver ton fichier dans library/My/Acl/Config.php.
Biensûr rien n'est obligatoire, il s'agit de l'organisation la plus courante.
Après ce n'est pas idiot de placer la définition de tes ACL dans l'application comme tu l'as fait. Mais à ce moment là tu dois comme je te l'ai dis, déclarer le nouveau type de resource à Zend. Et ensuite créer tes fichiers en les préfixant du namespace de ton module par défaut puisque c'est là qu'elles se trouveront.
De mon côté je ne place dans la librairie que ce qui pourra être commun d'un projet à un autre. Par exemple j'aurai une classe qui étend Zend_Acl et qui redéfinie son fonctionnement, mais ce n'est pas là que je créerai les rôles et les ressources. Celà je le fais, comme toi tu l'as décidé, dans une classe qui se trouve dans le dossier de l'application puisque c'est spécifique à ce projet, alors que ma librairie je vais la ré-utiliser dans d'autres applications.
Exemple, tu as:
protected function _initAutoload() { $autoloader = new Zend_Application_Module_Autoloader(array( 'basePath' => dirname(__FILE__), 'namespace' => 'App_', // il pourrait n'y avoir aucun namespace )); return $autoloader; }
Puis:
application/ acls/ Config.php
Tu déclares le nouveau type de resource à l'autoloader:
$moduleLoader->addResourceType('acl', 'acls', 'Acl'); // type, chemin, namespace
Et ensuite ta classe se nommera tout simplement App_Acl_Config.
(ou Acl_Config si tu as décidé de ne pas utiliser de namespace pour le module par défaut).
A+ benjamin.
Hors ligne
Merci Benjamin pour ces lumières,
il est vrai que je ne comprenais pas les différences et que c'est vraiment clair cette fois... MERCI
Sinon j'ai bien compris le système de nom des classes en fonction des emplacements, je ne comprenais pas la comment différencier les modules et la lib
; application.ini
autoloaderNamespaces[] = "My_"
Ca aide et du coup l'appel
$acl = new My_Acl();
fonctionne avec le fichier acl.php dans lib/My/
Par contre ce que je ne comprend encore pas (désolé ) c'est la redéfinition
Benjamin a écrit:
Code:
$moduleLoader->addResourceType('acl', 'acls', 'Acl'); // type, chemin, namespace
D'où vient $moduleLoader et où dois je le mettre dans protected function _initAutoload()?
Dede
Hors ligne
protected function _initAutoload() {
$moduleLoader = new Zend_Application_Module_Autoloader(
array('namespace' => '',
'basePath' => APPLICATION_PATH));
$moduleLoader->addResourceType(
....
Hors ligne
C'est bien ce que je pensais, du coup je peut l'appeler de cette façon dans le Bootstrap ?
protected function _initControllersPlugins() { $acl = new App_Acl_Config(); // Au lieu de My_Acl(); $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new App_Plugin_Controller_Acl($acl)); }
J' essaye maintenant d'approfondir la gestion via les Acl, mais le principe de mettre dans application ce qui est relatif au projet est intéressant par contre, je n'ai pas tout saisit à ce niveau :
Benjamin a écrit:
Par exemple j'aurai une classe qui étend Zend_Acl et qui redéfinie son fonctionnement, mais ce n'est pas là que je créerai les rôles et les ressources.
Ça à l'air plutôt bien mais je laisse ça pour plus tard... une fois compris
Hors ligne
Une dernière question :
J'ai constaté que lors de l'authentification, il ne prenait pas en compte la casse ?
Que le mette :
login ou Login ou LoGin ...etc et
pass ou Pass ou PaSs,
Il valide l'authentification ?
public function loginAction() { $this->view->message = ""; if ($this->getRequest()->isPost()) { //FILTRAGE DES INFORMATION RECUT DE LA PAGE LOGIN $f = new Zend_Filter_StripTags(); $user = $f->filter($this->getRequest()->getParam('login')); $pass = $f->filter($this->getRequest()->getParam('password')); if(empty($user)){ $this->view->message = "Veullez Saisir un Login."; }else{ //INITIALISATION DE LA RESSOURCE DB $bootstrap = $this->getInvokeArg('bootstrap'); $db = $bootstrap->getResource('db'); //DEFINITION DE LA TABLE ET DES COLONNES UTILES $authAdapter = new Zend_Auth_Adapter_DbTable($db, 'user', 'login', 'password', 'SHA1(?)'); $authAdapter->setIdentity($user) ->setCredential($pass); //TEST DES VALEURS $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter); //TRAITEMENT DU RESULT switch ($result->getCode()) { case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND: $this->view->message = utf8_encode("Erreur : Indentitée invalide"); break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: $this->view->message = utf8_encode("Erreur : Mot de passe incorrect"); break; case Zend_Auth_Result::SUCCESS: $data = $authAdapter->getResultRowObject(null, 'password'); $auth->getStorage()->write($data); $this->_redirect('/index'); break; default: $this->view->message = utf8_encode("Erreur : Non Définit"); break; } } } }
Avec un simple <form></fom> dans le script login du contrôleur.
Hors ligne
Pages: 1