2010-02-16 16 views
9

He basado mi aplicación en Zend Framework. Estoy usando Zend_Auth para la autenticación, pero no estoy seguro de si Zend_Acl me funcionará porque, francamente, los ejemplos que he visto son demasiado simplistas para mis necesidades o me confunden.¿Zend ACL se adapta a mis necesidades?

Estoy pensando en elementos en mi aplicación como Recursos y estos Recursos pueden tener privilegios. Las funciones que contienen privilegios de recursos se definen dinámicamente y se asignan a los usuarios. Estoy almacenando esta información en tablas normalizadas.

  1. Los usuarios tienen un papel
  2. Un papel puede tener múltiples recursos
  3. Los recursos pueden tener múltiples privilegios

papeles son en realidad sólo colecciones de los privilegios de recursos con ninguna jerarquía. Un ejemplo de un recurso sería 'Página'. Todos pueden ver las páginas, pero un usuario autenticado necesitaría privilegios de 'agregar', 'editar' o 'eliminar' para hacer cualquier otra cosa con las páginas.

¿Esta malla con Zend ACL? ¿Estoy pensando en ACL de una manera que me va a crear problemas?


mi solución

Typeonerror se lleva el crédito, pero aquí está mi solución específica.

extendí Zend_Acl para simplificar el uso de mi porque yo sólo carga el papel del usuario actual:

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); 
    } 
} 

para poblar la ACL ejecuto una consulta que devuelve resource, privilege y role_id columnas. La columna role_id es nula en el conjunto de resultados si la función del usuario no tiene ese 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']); 
    } 
} 

Respuesta

10

Así es exactamente como funciona y creo que estás pensando en ello de forma precisa. Puede agregar sus recursos y luego agregar privilegios para permitir que ciertos roles de usuario accedan a ellos. Por ejemplo, en mi CMS, tengo "desarrolladores", "administradores" y "usuarios". En el siguiente código agrego acceso general y luego elimino algunas acciones y métodos específicos del acceso de ciertos usuarios. Por supuesto, esto es bastante específico para mi aplicación, pero básicamente, tendría que obtener el rol del usuario de auth-> getIdentity() (o similar) y luego agregar sus roles/recursos de la base de datos.

<?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; 
    } 

} 

Editar

supongo que también debe explicar que tengo una Typeoneerror_Controller_Plugin_Acl que se utiliza siempre que se solicite cualquier recurso. Aquí creo la "etiqueta" que hace el recurso solicitado y verifico si el usuario tiene acceso a esa etiqueta:

$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

Estoy viendo los niveles de Usuario, Rol y Recurso en su ejemplo. Tengo usuario, función, recurso, privilegio. Un Usuario tiene un Rol, un Rol puede tener múltiples Recursos, y un Recurso puede tener múltiples Privilegios. ¿Estoy malentendiendo algo en tu solución? – Sonny

+0

Suena bien. La forma en que los usuarios están configurados, cada usuario hereda los privilegios de su padre.Entonces "admin" obtiene todos los privilegios de "invitado" y "miembros". Bajo administración, dejo "todo" y luego niego la acción de "purga" en todos los recursos y denego la acción "crear" solo en el recurso "cms: comentarios". Entonces todavía pueden acceder a las acciones "cms: comments-> view" o "cms: comments-> moderate". – typeoneerror

+0

Agregó un código. – typeoneerror

Cuestiones relacionadas