2010-12-22 46 views
3

我有一個MySQL數據庫表像的下面,資源表PHP MySQL的Zend公司的ACL - 以圖形方式顯示ACL:

+----+-----------+------------+ 
| id | name  | type  | 
+----+-----------+------------+ 
| 1 | guest  | user  | 
| 2 | member | user  | 
| 3 | moderator | user  | 
| 4 | owner  | user  | 
| 5 | admin  | user  | 
| 6 | index  | controller | 
+----+-----------+------------+ 

到下表中,規則表

+----+---------+------+-------------+----------------------+ 
| id | user_id | rule | resource_id | extras    | 
+----+---------+------+-------------+----------------------+ 
| 1 | 2  | 3 | 1   | null     | 
| 2 | 3  | 3 | 2   | null     | 
| 3 | 4  | 3 | 3   | null     | 
| 4 | 5  | 3 | 4   | null     | 
| 5 | 6  | 1 | 1   | index,login,register | 
| 6 | 6  | 2 | 2   | login,register  | 
| 7 | 6  | 1 | 2   | logout    | 
+----+---------+------+-------------+----------------------+ 

OK,遺憾的長度,但我TR讓我全面瞭解我想要做的事情。 所以它的工作方式,角色(又名用戶)可以授予(規則:1)訪問控制器,一個角色可以繼承(規則:3)從另一個角色訪問或一個角色並被拒絕(規則:2)訪問控制器。 (A 用戶是資源和控制器是一個資源)

訪問操作被授予使用所述額外柱/拒絕。

這一切都有效,它在zend中設置ACL時不存在問題。


我現在試圖做的是顯示關係;要做到這一點,我需要找到最低級別的角色被授予訪問控制器,如果它已明確被刪除,停止。我計劃列出角色。當我點擊角色時,我希望它顯示角色有權訪問的所有控制器。然後點擊一個控制器會顯示該角色被允許執行的操作。

所以在上面的例子中,guest允許查看索引控制器的索引操作以及登錄操作。 成員繼承相同的訪問權限,但拒絕訪問登錄操作和註冊操作。 主持人繼承成員的規則。

所以,如果我選擇角色主持人。我想看到列出的控制器索引。如果我點擊控制器,它應該顯示允許的操作爲操作:索引。 (最初授予客人,但此後並未被解除)

是否有任何這樣做的例子。我顯然正在使用Zend MVC(PHP)和MySQL。 即使只是一個persudo代碼示例將是一個有用的起點 - 這是我拼湊在一起的拼圖的最後部分之一。

P.S.很明顯,我有ACL對象 - 這會更容易插入,還是更好地通過PHP/MySQL來完成我的自我?

目標是,顯示一個角色可以訪問的角色,然後允許我添加或編輯GUI風格的角色,控制器和動作(這有點簡單) - 目前我正在更新數據庫手動,因爲我一直在建設該網站。

回答

2

好吧,我沒有找到答案,我沒有找到答案,我有點更多的思考這個問題,這是我想出的解決方案(只是說明它對別人有用)

的僞第一:

  1. 顯示一個頁面上,從ACL列出所有角色(用戶級別)$acl->getRoles()作爲鏈接。
  2. 單擊一個鏈接,重新加載通過角色作爲參數的頁面。
    • 現在抓住所有的控制器從ACL $acl->getResources()檢查insn't作用資源(通過getResources返回的數組也將包含角色)
    • 遍歷每個控制器,讓所有條目從規則表,其中控制器 ID是在RESOURCE_ID領域和爆炸額外(逗號分隔的動作)
    • 接下來,遍歷每個動作,呼籲isAllowed(我有角色,控制器和行動)IF至少一個「允許」被發現,我色控制器綠色(允許訪問控制器中的至少一個動作),否則其紅(不以任何訪問該控制器)每個列表項是點擊重新加載頁面
  3. 現在點擊控制器的時候,我重新加載頁面,現在,通過操作列表中運行時,調用isAllowed創建選定控制器的操作的列表,着色作用綠色或紅色的結果isAllowed

自己的答案几乎與問題一樣囉嗦,但它對我很有用,給出了每個角色可以做什麼的清晰畫面。這是如果要幫助的人:

現在的代碼:

AdminController:

public function aclAction() 
{ 
    $this->view->content_title = "Access Rules:"; 

    // Get the ACL - its stored in the session: 
    $usersNs = new Zend_Session_Namespace("ZEND_SITE"); 
    $acl = $usersNs->acl; 

    // List all Roles in the ACL: 
    $roles = $acl->getRoles(); 
    // Pass the roles to the view: 
    $this->view->roles = $roles; 

    // Check if a role has been clicked on: 
    $role = this->_getParam('role'); 
    if(!is_null($role)) 
    { 
     // Pass the role to the view: 
     $this->view->role = $role; 

     // Get all the resources (controllers) from the ACL, don't add roles: 
     $controllers = array(); 
     foreach ($acl->getResources() as $res) 
     { 
      if (!in_array($res, $roles)) 
      { 
       $controllers[] = $res; 
      } 
     } 

     // Create a Rules Model: 
     $rules = new Model_ACLrules(); 

     // Store controllers + access: 
     $all_controllers = array(); 

     // Check if the controller has been passed: 
     $cont = $this->_getParam('cont'); 

     // Loop through each controller: 
     foreach ($controllers as $controller) 
     { 
      // Get all actions for the controller: 
      // THIS IS THE PART I DON'T LIKE - BUT I SEE NO WAY TO GET 
      // THE RULES FROM THE ACL - THERE LOOKS TO BE A METHOD 
      // BUT IT IS A PROTECTED METHOD - SO I AM GETTING THE ACTIONS 
      // FROM THE DB, BUT THIS MEANS TWO SQL QUERIES - ONE TO FIND 
      // THE RESOURCE FROM THE DB TO GET ITS ID THEN ONE TO FIND 
      // ALL THE EXTRAS FOR IT: 
      $all_rules = $rules->findAllActions($controller); 

      // Store if the role is allowed access somewhere in the controller: 
      $allowed = false; 

      // Store selected controller actions: 
      $cont_actions = array(); 

      // Loop through all returned row of actions for the resource: 
      foreach ($all_rules as $rule) 
      { 
       // Split the extras field: 
       $extras = explode(",", $rule->extras); 

       // Check if the role has access to any of the actions: 
       foreach ($extras as $act) 
       { 
        // Store matching selected controller: 
        $match = ($cont==$controller)?true:false; 

        // Store the action if we are looking at a resource: 
        if ($match)$temp = array("action"=>$act,"allowed"=>false); 

        // Check if the role is allowed: 
        if ($acl->isAllowed($role,$controller,$act)) 
        { 
         // Change the controllers allowed to ture as at least one item is allowed: 
         $allowed = true; 

         // Change the matched controllers action to true: 
         if ($match)$temp = array("action"=>$act,"allowed"=>true); 
        } 

        // Check if the action has already been added if we are looking at a resource: 
        if ($match) 
        { 
         $add = true; 
         // This is done because there could be several rows of extras, for example 
         // login is allowed for guest, then on another row login is denied for member, 
         // this means the login action will be found twice for the resource, 
         // no point in showing login action twice: 
         foreach ($cont_actions as $a) 
         { 
          // Action already in the array, don't add it again: 
          if ($a['action'] == $act) $add = false; 
         } 
         if($add) $cont_actions[] = $temp; 
        } 
       } 
      } 

      // Pass a list of controllers to the view: 
      $all_controllers[] = array("controller" => $controller, "allowed" => $allowed); 

      // Check if we had a controller: 
      if(!is_null($cont)) 
      { 
       // Pass the selected controller to the view: 
       $this->view->controller = $cont; 

       // Check if this controller in the loop is the controller selected: 
       if ($cont == $controller) 
       { 
        // Add the controller + actions to the all rules: 
        $this->view->actions = $cont_actions; 
       } 
      } 
     } 

     // Pass the full controller list to the view: 
     $this->view->controllers = $all_controllers; 
    } 
} 

下一頁的觀點:訪問控制列表。PHTML:

<h2>Roles:</h2> 
<ul> 
    <?php 
     foreach ($this->roles as $name) 
     { 
      echo '<li><a href="'.$this->baseUrl('admin/acl') . '/role/' . $name . '">' . ucfirst($name) . '</a><br/></li>'; 
     } 
    ?> 
</ul> 

<?php if (isset($this->controllers)): ?> 
    <h2><?php echo ucfirst($this->role); ?>'s Controllers:</h2> 
    <ul> 
     <?php 
      $array = $this->controllers; 
      sort($array); 
      foreach ($array as $controller) 
      { 
       $font = ($controller['allowed'])?'green':'red'; 
       echo '<li><a href="'.$this->baseUrl('admin/acl') . '/role/' . $this->role . '/cont/'.$controller['controller'].'" style="color:'.$font.';">'.ucfirst($controller['controller']).'</a></li>';  
      } 
     ?> 
    </ul> 

    <?php if (isset($this->controller)): ?> 
     <h2><?php echo ucfirst($this->role)."'s, ".ucfirst($this->controller);?> Actions:</h2> 
     <ul> 
      <?php 
       $array = $this->actions; 
       sort($array); 
       foreach ($array as $action) 
       { 
        $font = ($action['allowed'])?'green':'red'; 
        echo '<li><font style="color:'.$font.';">'.ucfirst($action['action']).'</font></li>'; 
       } 
      ?> 
     </ul> 
    <?php endif;?> 
<?php endif; ?> 

例子:

我希望這是有幫助的人,我會離開它打開,現在櫃面任何人都可以提出一個更好的解決方案 - 或對答案可能提高?

1
public function aclAction() 
{ 
    $this->disableView(); 

    $service = $this->service()->acl(); 
    $acl = $service->getAcl(); 
    $roles = $acl->getRoles(); 
    $resources = $acl->getResources(); 
    $results = array(); 

    // load XML to get all rules & roles & actions 
    $configdata = $service->getConfigdata(); 

    $actions = array(); 
    foreach ($configdata['rules']['rule'] as $rule){ 
     if(isset($rule['action'])){ 
      if(!is_array($rule['action'])) 
       $rule['action'] = array($rule['action']); 
      foreach($rule['action'] as $action){ 
       $actions[$rule['resource']][$action] = $action; 
      } 
     } 

    } 

    $results[] = 
    '<thead>' 
    . '<tr>' 
    .  '<th>Resource</th>' 
    .  '<th>Action</th>' 
    .  '<th colspan="'.count($roles).'">Roles</th>' 
    . '</tr>' 
    . '<tr>' 
    .  '<th></th>' 
    .  '<th></th>'; 

    foreach ($roles as $role){ 
     $results[] = '<th>'.$role.'</th>' . PHP_EOL; 
    } 
    $results[] = '</tr></thead>' . PHP_EOL; 
    $results[] = '<tbody>'; 

    foreach ($resources as $resource){ 

     $results[] = '<tr><th>'.$resource.'</th><td>-</td>'; 
     foreach ($roles as $role){ 
      $test = $acl->isAllowed($role, $resource); 
      $results[] = '<td'.($test?' class="green"':' class="red"').'>'.($test?'YES':'NO').'</td>'; 
     } 
     $results[] = '</tr>'; 

     if(isset($actions[$resource])){ 
      foreach ($actions[$resource] as $action){ 

       $results[] = '<tr><th>&rarr;</th><td>'.$action.'</td>'; 
       foreach ($roles as $role){ 
        $test = $acl->isAllowed($role, $resource, $action); 
        $results[] = '<td'.($test?' class="green"':' class="red"').'>'.($test?'YES':'NO').'</td>'; 
       } 
       $results[] = '</tr>'; 
      } 
     } 
    } 

    echo 
    '<style type="text/css">' 
    . 'html, body, table {font-family:verdana;font-size:14px;}' 
    . 'table {border-spacing:1px;background:#CCCCCC;}' 
    . 'td, th {background:#ffffff;padding:5px;}' 
    . 'th {text-align:left;}' 
    . 'tr:nth-child(even) td, tr:nth-child(even) th {background:#C2DBEF;}' 
    . '.red {color:red;font-weight:bold;}' 
    . '.green {color:green;font-weight:bold;}' 
    .'</style>' 
    .'<h1>$role is allowed to $resource ?</h1>' 
    .'<table>'.implode('', $results).'</table>'; 

} 

例子:http://i.stack.imgur.com/1tR3g.png(這裏我是一個客人,我不能發表圖片) 我從我的項目複製它 - 希望它幫助。它的動作看起來很不錯,但是你需要一個合適的xml以及所有規則等。