PHP MySQL的Zend公司的ACL - 以图形方式显示ACL:

PHP MySQL的Zend公司的ACL - 以图形方式显示ACL:

问题描述:

我有一个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风格的角色,控制器和动作(这有点简单) - 目前我正在更新数据库手动,因为我一直在建设该网站。

好吧,我没有找到答案,我没有找到答案,我有点更多的思考这个问题,这是我想出的解决方案(只是说明它对别人有用)

的伪第一:

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

例子:

我希望这是有帮助的人,我会离开它打开,现在柜面任何人都可以提出一个更好的解决方案 - 或对答案可能提高?

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以及所有规则等。