2010-02-16 8 views
9

Ho basato la mia applicazione su Zend Framework. Sto usando Zend_Auth per l'autenticazione, ma non sono sicuro che l'Zend_Acl funzionerà per me perché, francamente, gli esempi che ho visto sono troppo semplicistici per i miei bisogni o mi confondono.Zend ACL soddisfa le mie esigenze?

Sto pensando a elementi nella mia applicazione come risorse e queste risorse possono avere privilegi. I ruoli che contengono i privilegi di risorsa sono definiti dinamicamente e assegnati agli utenti. Sto memorizzando queste informazioni in tabelle normalizzate.

  1. Gli utenti hanno un ruolo
  2. Un ruolo può avere più risorse
  3. risorse possono avere più privilegi

ruoli sono in realtà solo le collezioni di privilegi di risorse con nessuna gerarchia. Un esempio di una risorsa sarebbe "Pagina". Tutti possono visualizzare le pagine, ma un utente autenticato avrebbe bisogno dei privilegi "aggiungi", "modifica" o "cancella" per fare qualsiasi altra cosa con le pagine.

Questa mesh con Zend ACL? Sto pensando ACL in un modo che creerà problemi per me?


mia soluzione

Typeonerror ottiene il credito, ma ecco la mia soluzione specifica.

ho esteso Zend_Acl per semplificare l'uso della mia perché io carico solo il ruolo dell'utente corrente:

class My_Acl extends Zend_Acl 
{ 
    protected $_role_id; 

    public function setRole($role_id) 
    { 
     $this->_role_id = $role_id; 
     return $this->addRole($role_id); 
    } 

    public function getRole() 
    { 
     return $this->_role_id; 
    } 

    public function deny($resource, $privilege) 
    { 
     return parent::deny($this->_role_id, $resource, $privilege); 
    } 

    public function allow($resource, $privilege) 
    { 
     return parent::allow($this->_role_id, $resource, $privilege); 
    } 

    public function isAllowed($resource, $privilege) 
    { 
     return parent::isAllowed($this->_role_id, $resource, $privilege); 
    } 
} 

per popolare il LCA eseguo una query che restituisce resource, privilege e role_id colonne. La colonna role_id è nullo nel set di risultati se il ruolo dell'utente non dispone di tale privilegio.

$acl = new My_Acl(); 

$auth = Zend_Auth::getInstance(); 
if ($auth->hasIdentity()) { 
    $userInfo = $auth->getStorage()->read(); 
    $acl->setRole($userInfo->role_id); 
} else { 
    $acl->setRole(''); 
} 

// QUERY HERE 

foreach ($privileges as $privilege) { 
    if (!$acl->has($privilege['resource'])) { 
     $acl->addResource($privilege['resource']); 
    } 
    if (is_null($privilege['role_id'])) { 
     $acl->deny($privilege['resource'], $privilege['privilege']); 
    } else { 
     $acl->allow($privilege['resource'], $privilege['privilege']); 
    } 
} 

risposta

10

Questo è esattamente come funziona e penso che ci stai pensando in modo accurato. È possibile aggiungere le risorse e quindi aggiungere privilegi per consentire a determinati ruoli utente di accedervi. Ad esempio, nel mio CMS, ho "sviluppatori", "amministratori" e "utenti". Nel codice seguente aggiungo l'accesso generale e quindi rimuovo alcune azioni e metodi specifici dall'accesso di determinati utenti. Naturalmente questo è abbastanza specifico per la mia applicazione, ma fondamentalmente, dovresti ottenere il ruolo dell'utente da auth-> getIdentity() (o simile) e quindi aggiungere i tuoi ruoli/risorse dal database.

<?php 

/** 
* @author  Benjamin Borowski <[email protected]> 
* @copyright Copyright (c) Typeoneerror Studios http://typeoneerror.com 
* @version $Id$ 
* @category Typeoneerror 
* @package Acl 
*/ 

/** 
* Defines basic roles and resources for an application as 
* well as a Content Management System (CMS). 
* 
* Zend_Acl provides a lightweight and flexible access control list 
* (ACL) implementation for privileges management. 
* 
* {@inheritdoc} 
* 
* @author  Benjamin Borowski <[email protected]> 
* @copyright Copyright (c) Typeoneerror Studios http://typeoneerror.com 
* @version $Id$ 
* @category Typeoneerror 
* @package Acl 
*/ 
class Typeoneerror_Acl extends Zend_Acl 
{ 
    /** 
    * Constructor function. 
    * 
    * Creates basic roles and resources and adds them to Acl. 
    * 
    * {@inheritdoc} 
    * 
    * @return Typeoneerror_Acl 
    */ 
    public function __construct() 
    { 
     //--------------------------------------- 
     // ROLES 
     //--------------------------------------- 

     $this->_addRole("guest") 
      ->_addRole("member", "guest") 
      ->_addRole("admin", "member") 
      ->_addRole("developer", "admin"); 

     //--------------------------------------- 
     // FRONT-END RESOURCES 
     //--------------------------------------- 

     $this->_add("default"); 

     //--------------------------------------- 
     // BACK-END RESOURCES 
     //--------------------------------------- 

     $this->_add("cms") 
      ->_add("cms:articles", "cms") 
      ->_add("cms:auth", "cms") 
      ->_add("cms:bug-report", "cms") 
      ->_add("cms:calendar", "cms") 
      ->_add("cms:categories", "cms") 
      ->_add("cms:comments", "cms") 
      ->_add("cms:error", "cms") 
      ->_add("cms:galleries", "cms") 
      ->_add("cms:pages", "cms") 
      ->_add("cms:photos", "cms") 
      ->_add("cms:tags", "cms") 
      ->_add("cms:users", "cms"); 

     //--------------------------------------- 
     // GUEST PERMISSIONS 
     //--------------------------------------- 

     $this->allow("guest", "default") 
      ->allow("guest", "cms:auth")   // -- guests can attempt to log-in 
      ->allow("guest", "cms:error")   // -- guests can break stuff 
      ->allow("guest", "cms:bug-report"); // -- guests can report bugs 

     //--------------------------------------- 
     // ADMIN PERMISSIONS 
     //--------------------------------------- 

     $this->allow("admin") 
      ->deny("admin", null, "purge")      // -- admins cannot purge (normally) 
      ->deny("admin", "cms:comments", "create");   // -- only devs can create a comment 

     //--------------------------------------- 
     // DEVELOPER PERMISSIONS 
     //--------------------------------------- 

     $this->allow("developer");    // -- unrestricted access 

     return $this; 
    } 

    /** 
    * Adds a Resource having an identifier unique to the ACL. 
    * 
    * @param Zend_Acl_Resource_Interface $resource  The resource to add 
    * @param Zend_Acl_Resource_Interface|string $parent A parent resource it inherits from 
    * @return Typeoneerror_Acl       Reference to Acl class 
    */ 
    protected function _add($resource, $parent = null) 
    { 
     $this->add(new Zend_Acl_Resource($resource), $parent); 

     return $this; 
    } 

    /** 
    * Wrapper for <code>addRole</code> 
    * 
    * @param Zend_Acl_Resource_Interface $resource  The resource to add 
    * @param Zend_Acl_Resource_Interface|string $parents Parent resources it inherits from 
    * @return Typeoneerror_Acl       Reference to Acl class 
    */ 
    protected function _addRole($role, $parents = null) 
    { 
     $this->addRole(new Zend_Acl_Role($role, $parents)); 

     return $this; 
    } 

} 

Modifica

che dovrei anche spiegare che ho un Typeoneerror_Controller_Plugin_Acl che viene utilizzato ogni volta che viene richiesto alcuna risorsa. Qui creo il "tag" che la risorsa richiesta fa e verificare se l'utente ha accesso a quel tag:

$controller = $request->controller; 
    $action = $request->action; 
    $module = (empty($request->module)) ? "default" : $request->module; 

    // -- this ends up like "cms:articles" just like my resources 
    $resource = $module . ":" . $controller; 

    if (!$this->__acl->has($resource)) 
    { 
     $resource = $module; 
    } 

    // -- the good stuff. check if the user's role can access the resource and action 
    if (!$this->__acl->isAllowed($role, $resource, $action)) 
    { 
     //more code 
    } 
+0

sto vedendo i livelli di utenti, ruoli e risorse nel tuo esempio. Ho utente, ruolo, risorsa, privilegio. Un utente ha un ruolo, un ruolo può avere più risorse e una risorsa può avere più privilegi. Sto fraintendendo qualcosa nella tua soluzione? – Sonny

+0

Suoni di destra. Il modo in cui gli utenti sono impostati, ogni utente eredita i privilegi dal suo genitore.Quindi "admin" ottiene tutti i privilegi "guest" e "members". Sotto admin, consento "all" e quindi negare l'azione "purge" su tutte le risorse e negare l'azione "create" solo sul resume "cms: comments". In questo modo possono ancora accedere alle azioni "cms: comments-> view" o "cms: comments-> moderate". – typeoneerror

+0

Aggiunto un po 'di codice. – typeoneerror