2010-02-16 18 views
9

Oparłem moją aplikację na Zend Framework. Używam Zend_Auth do uwierzytelniania, ale nie jestem pewien, czy Zend_Acl będzie działać dla mnie, ponieważ, szczerze mówiąc, przykłady, które widziałem są albo zbyt uproszczone dla moich potrzeb, albo wprowadzają w błąd.Czy Zend ACL odpowiada moim potrzebom?

Mam na myśli elementy w mojej aplikacji jako Zasoby, a te Zasoby mogą mieć uprawnienia. Role zawierające uprawnienia do zasobów są definiowane dynamicznie dla użytkowników. Przechowuję te informacje w znormalizowanych tabelach.

  1. Użytkownicy mają rolę
  2. rolę może mieć wiele zasobów
  3. Zasoby mogą mieć wiele Uprawnienia

role są naprawdę tylko zbiory przywilejów Zasobów bez hierarchii. Przykładem zasobu będzie "Strona". Każdy może przeglądać strony, ale uwierzytelniony użytkownik będzie potrzebować uprawnień "dodaj", "edytuj" lub "usuń", aby zrobić cokolwiek innego ze stronami.

Czy jest to zgodne z Zend ACL? Czy ja myślę o ACL w sposób, który będzie dla mnie źródłem problemów?


moje rozwiązanie

Typeonerror dostaje kredyt, ale tutaj jest moje specyficzne rozwiązanie.

ja przedłużony Zend_Acl uprościć moje zużycie bo tylko załadować roli bieżącego użytkownika:

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

aby wypełnić ACL I wykonanie kwerendy, która zwraca resource, privilege i role_id kolumn. Kolumna role_id ma wartość NULL w zestawie wyników, jeśli rola użytkownika nie ma tego uprawnienia.

$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']); 
    } 
} 

Odpowiedz

10

Dokładnie to działa i myślę, że myślisz o tym w dokładny sposób. Możesz dodać swoje zasoby, a następnie dodać uprawnienia, aby umożliwić niektórym rolom użytkowników dostęp do nich. Na przykład w moim CMS mam "programistów", "adminów" i "użytkowników". W poniższym kodzie dodaję ogólny dostęp, a następnie usuwam niektóre akcje i określone metody z dostępu dla określonego użytkownika. Oczywiście jest to dość specyficzne dla mojej aplikacji, ale w zasadzie musielibyście uzyskać rolę użytkownika z auth-> getIdentity() (lub podobnego), a następnie dodać swoje role/zasoby z bazy danych.

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

} 

Edit

Chyba powinna również wyjaśnić, że mam Typeoneerror_Controller_Plugin_Acl który jest używany, gdy każdy zasób jest wymagana. Tutaj tworzę "tag", który żądany zasób tworzy i sprawdza, czy użytkownik ma dostęp do tego tagu:

$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

Widzę poziomy użytkowników, roli i zasobów w twoim przykładzie. Mam użytkownika, rolę, zasoby, przywilej. Użytkownik ma jedną rolę, rola może mieć wiele zasobów, a zasób może mieć wiele uprawnień. Czy nie rozumiem czegoś w twoim rozwiązaniu? – Sonny

+0

Dźwięki o prawej. Sposób, w jaki użytkownicy są skonfigurowani, każdy użytkownik dziedziczy uprawnienia od rodzica.Tak więc "admin" otrzymuje wszystkie uprawnienia "guest" i "members". Pod adminem zezwalam na "wszystko", a następnie odmawiam akcji "oczyść" wszystkich zasobów i odmawiam akcji "twórz" tylko w przypadku "cms: comments". Dzięki temu mogą uzyskać dostęp do działań "cms: comments-> view" lub "cms: comments-> moderate". – typeoneerror

+0

Dodano kod. – typeoneerror