2011-09-13 64 views
16

爲自定義應用程序設計專用ACL系統時出現了這個問題,但我認爲它適用於一般的ACL系統,因爲我還沒有發現如何解決這個問題通過看一些主流系統,如Zend_ACL構建'雙向'OO動態ACL系統

在我的應用程序中,權限是動態授予的,例如:用戶獲取某活動的查看權限,因爲他是該活動所鏈接到的團隊的成員。這建立在假定你總是有一個Employee(用戶)想要對Item(我的應用程序中的一個對象,例如Activity,Team等)執行操作(查看/編輯/等)。這對我的目標使用來說已經足夠了。

$Activity = new Activity($_POST['activity_id']); 

$Acl = new Acl($Activity); 
if (!$Acl->check('edit') { 
    throw new AclException('no permission to edit'); 
} 

Acl類包含所有的業務規則,以授予的權限,他們是「對飛」創建(儘管有時緩存性能的原因);

/** 
* Check the permissions on a given activity. 
* @param Activity $Activity 
* @param int $permission (optional) check for a specific permission 
* @return mixed integer containing all the permissions, or a bool when $permission is set 
*/ 
public function checkActivity(Activity $Activity, $permission = null) { 
    $permissions = 0; 

    if ($Activity->owner_actor_id == $this->Employee->employee_id) { 
     $permissions |= $this->activity['view']; 
     $permissions |= $this->activity['remove']; 
     $permissions |= $this->activity['edit']; 
    } elseif (in_array($this->Employee->employee_id, $Activity->contributor_ids_arr)) { 
     $permissions |= $this->activity['view']; 
    } else { 
     /** 
     * Logged in user is not the owner of the activity, he can contribute 
     * if he's in the team the activity is linked to 
     */ 
     if ($Activity->getTeam()->isMember($this->Employee)) { 
      $permissions |= $this->activity['view']; 
     } 
    } 

    return ($permission ? (($permission & $permissions) === $permission) : $permissions); 
} 

該系統按原樣正常工作。

當您想要「反向」ACL規則時,會出現此方法的問題。例如,「獲取我可以編輯的所有活動」。我不想在需要這些活動的代碼中放入任何邏輯,例如WHERE owner_actor_id = $Employee->employee_id,因爲這是Acl類的職責,應該保持集中。在目前的實現中,我沒有別的選擇來獲取代碼中的所有活動,然後逐個聲明它們。這當然是一種非常低效的方法。

所以,我正在尋找的是一個良好的架構(或指向現有ACL實現或一些相關的設計模式)的一些想法來創建一個ACL系統,該系統能以某種方式做到既hasPermission($Item, $permission)fetchAllItems($permission),最好用相同的業務規則集。

謝謝大家提前!


我已經看過Zend_ACL的實現,但更多地關注於一般權限。我還發現了以下問題在這裏SO:

但不幸的是他們似乎並不要麼回答這個問題。

+0

什麼是反對把'fetchAllItems參數()'方法在'Acl'課程?我不確定我真的明白這個問題。 – erisco

回答

1

一位同事向我提出了關於此事的另一種看法,這也可能是解決這個問題的辦法。

以爲我想是放在ACL類所有接入相關的代碼(鏡像我聲明「我不想把任何邏輯一樣WHERE owner_actor_id = $Employee->employee_id在需要的活動代碼,因爲這是Acl類的責任,應該保持集中。「)。

我真的是什麼確保用戶不能訪問的東西,不符合在ACL類中列出的規則。如果「工作者代碼」已經獲取了數據的一個子集 - 只要它最終與「真正」的ACL進行了檢查,那麼這不是真的問題。可能發生的最糟糕的情況是用戶看到的比他應該看到的要少,這比好得多。使用此「解決方案」(如果您願意,可以採用其他方法),您可以避免獲取所有數據,同時保持將所有規則集中到一個地方的好處。我能想到的任何其他解決方案都會涉及到規則的重複,因爲您需要PHP中的規則來檢查給定的資源,以及使用MySQL中編寫的規則來獲取所有規則。

順便提一下,仍然有可能將子集提取代碼放在Acl類中 - 但是我認爲最好讓類保持小而專注(因爲我認爲該類代碼的可讀性也很重要)。

+0

你介意多說一點嗎? – Xeoncross

+0

@ Xeoncross:當然,你不明白的是什麼? – Rijk

0

據我所知ACL應該用來檢查常規權限。基於實體的權限不應該是ACL的主題。對於這樣的任務,我將看看Linux/Unix如何管理文件權限。

  owner group all 
read  1  1  1 
write  1  0  0 
execute  1  0  0 
-------------------------------------- 
      7  4  4 

在類似的實現中,獲取和檢查權限都很簡單,但您需要嚮應用程序添加一個圖層。

編輯: 另外這個架構將尊重單一責任原則,只要檢查「如果用戶被允許打開一個頁面」不同於

+0

但這是一個權限系統,您只能看到所有者,組和所有實體,並且該權限的重要部分是擁有所有者。這是ACL,您將指定的用戶和組分配給某些操作並且繼承了規則和組規則。 –

+0

我無法看到'file'和'Activity object'之間的區別 - 它們都是'實體'的權利?用戶可以在實體上擁有一組權限,比如'查看','編輯','刪除','讀','寫','執行'等。我的系統和Linux的區別在於,我的權限是從上下文派生的,而不是每個實體的硬編碼。 – Rijk

0

這似乎是更「將在頁面中看到哪些用戶」如基於角色的訪問控制或RBAC,而不是訪問控制列表ACL,因爲您授予對象上的用戶權限取決於角色具有的權限,如果他們在組中,協作列表中或者是所有者,但您不是作爲角色存儲,因此不能成爲RBAC,但由於您假設它不能成爲ACL,因此您不存儲權限。

所以,如果你想通過你正在假設的權限來查詢一組對象,顯然你需要首先計算分配的權限才能得到它們。

然後,您可以在存儲過程/ udf函數中計算,如果您希望在數據庫中無法獲取所有數據,或者創建了ACL表/列表或者與您希望爲其授予權限的對象鏈接的角色權限。

希望這是有用的,很好的問題,它炸了一下我的大腦,但現在我需要做類似的東西..有一個愉快的一天

+0

感謝您的評論!我已經看過RBAC,但它似乎不適合我的情況。維基百科指出:「RBAC不是**動態分配授權的模式」 - 我相信動態分配是我在這裏要做的。 – Rijk

+0

我想說的一點是關於RBAC是一個集中訪問控制實體,並且需要向該實體請求授權以獲得授權給對象。另一方面,ACL具有鏈接或在對象中的列表,並且API詢問對象的ACL是否授予用戶訪問權限。如果你想在沒有從數據庫中獲取所有數據的情況下進行分配,你唯一的解決方案就是一個UDF函數/存儲過程,如果你懷疑如何寫它,請問這個問題。 –