2010-02-16 47 views
9

我的應用程序基於Zend框架。我使用Zend_Auth進行身份驗證,但我不知道是否會Zend_Acl爲我工作,因爲坦率地說,我見過的例子是無論是對我的需要過於簡單化或迷惑我。Zend ACL適合我的需求嗎?

我在考慮我的應用程序中的元素作爲資源,這些資源可以擁有特權。包含資源權限的角色是動態定義分配給用戶的。我將這些信息存儲在規範化的表格中。

  1. 用戶有一定的作用
  2. 一個角色可以有多個資源
  3. 資源可以有多個權限

角色其實只是沒有層次資源權限的集合。一個資源的例子是'Page'。每個人都可以查看頁面,但是經過身份驗證的用戶需要「添加」,「編輯」或「刪除」權限,才能對頁面進行其他操作。

這是否網與Zend ACL?我是否以一種會給我造成問題的方式思考ACL?


我的解決方案

Typeonerror得到榮譽,但在這裏我具體的解決方案。

我伸出Zend_Acl簡化我的使用,因爲我只加載當前用戶的角色:

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

要填充我執行一個查詢返回resourceprivilege,並role_id列的ACL。如果用戶的角色沒有該特權,則role_id列在結果集中爲空。

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

回答

10

這正是它的工作原理,我認爲你正在以準確的方式考慮它。您可以添加資源,然後添加權限以允許某些用戶角色訪問它們。例如,在我的CMS中,我有「開發人員」,「管理員」和「用戶」。在下面的代碼中,我添加了一般訪問權限,然後刪除某些用戶訪問的操作和特定方法。當然,這對我的應用程序來說非常具體,但基本上,您必須從auth-> getIdentity()(或類似)獲取用戶的角色,然後從數據庫添加您的角色/資源。

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

} 

編輯

想我也應該解釋,我只要有請求任何資源所使用的Typeoneerror_Controller_Plugin_Acl。在這裏,我創建了「標籤」所請求的資源製造和檢查用戶是否有權訪問標籤:

$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

我看到的用戶,角色的等級和資源在你的榜樣。我有用戶,角色,資源,特權。用戶具有一個角色,角色可以具有多個資源,並且資源可以具有多個權限。我是否誤解了解決方案中的某些內容? – Sonny 2010-02-17 15:11:15

+0

聽起來很正確。用戶設置的方式是,每個用戶從其父節點繼承權限。所以「管理員」獲得所有「客人」和「成員」特權。在管理員下,我允許「全部」,然後拒絕對所有資源執行「清除」操作,並僅對「cms:comments」資源拒絕「創建」操作。所以他們仍然可以訪問「cms:comments-> view」或「cms:comments-> moderate」操作。 – typeoneerror 2010-02-17 16:50:42

+0

增加了一些代碼。 – typeoneerror 2010-02-17 16:51:50