【问题标题】:Zend Framework: How to display multiple actions, each requiring different authorizations levels, on a single pageZend Framework:如何在单个页面上显示多个操作,每个操作都需要不同的授权级别
【发布时间】:2011-04-06 11:29:07
【问题描述】:

想象一下,我有 4 个数据库表,以及一个在单个网页上呈现用于管理每个表中数据的表单的界面(使用手风琴设计模式一次只显示一个表单)。每个表单都显示了表格中的行列表,允许用户插入新行或选择要编辑或删除的行。然后使用 AJAX 将请求发送到服务器。

必须根据应用程序 ACL 向不同用户显示一组不同的表单。

我的问题是:就控制器、动作、视图和布局而言,这个界面的最佳架构是什么?

例如,到目前为止,我有一个控制器,可以为每个表添加、编辑和删除操作。每个都有一个 indexAction,但它是一个空函数。我还为每个表扩展了 Zend_Form。为了显示表单,我在 IndexController 中将表单传递给它的视图,并回显每个表单。然后,Javascript 负责填充表单并将请求发送到相应控制器的适当添加/编辑/删除操作。但是,这不允许 ACL 控制表单对不同用户的显示与否。

最好让 indexAction 实例化表单,然后使用类似 $this->render();在IndexController 的indexAction 视图中呈现每个视图?然后 ACL 会阻止呈现某些视图吗?

干杯。

【问题讨论】:

    标签: zend-framework


    【解决方案1】:

    您可以在几个地方对您的 ACL 进行检查:

    1. 您有循环(或硬编码块)来加载每个表单。
    2. 在每个表单对象的构造函数中,可能会抛出一个自定义异常,该异常可以被捕获并适当处理。
    3. 来自 Zend_Form 扩展的构造函数,所有自定义 Form 对象都从该扩展构造函数中扩展(可能是最好的方法,因为它有助于减少代码重复)。

    请记住,如果您使用 ZF 为您的更新执行 AJAXy 解决方案,您的控制器还需要在其 init() 方法中运行 ACL 检查,以防止对您的数据库进行未经授权的更改。

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      这个问题你解决了吗?

      我正在构建一个大型数据库应用程序,其中包含许多嵌套的子控制器作为显示在父控制器上的仪表板上的面板。 简化的源代码如下:来自我的parentController->indexAction()

          $dashboardControllers = $this->_helper->model( 'User' )->getVisibleControllers();
          foreach (array_reverse($dashboardControllers) as $controllerName) // lifo stack so put them on last first
          {
              if ($controllerName == 'header') continue; // always added last
              // if you are wondering why a panel doesn't appear here even though the indexAction is called: it is probably because the panel is redirecting (eg if access denied). The view doesn't render on a redirect / forward
              $this->_helper->actionStack( 'index', $this->parentControllerName . '_' . $controllerName ); 
          }
          $this->_helper->actionStack( 'index', $this->parentControllerName . '_header' ); 
      

      如果您有更好的解决方案,我很想听听。 对于我的下一个技巧,我需要弄清楚如何根据用户偏好设置将这些显示在一列、两列或三列中

      【讨论】:

        【解决方案3】:

        我使用 Manning Press 的“Zend Framework in Action”一书中的修改版本(如果您现在需要,可以下载 PDF 格式)。我认为您可以从本书的站点下载随附的代码。你想看看第 7 章的代码。

        概述:

        控制器是资源,动作是权限。 将您的允许和拒绝放在控制器的 init 方法中。 我也在使用他们的 Controller_Action_Helper_Acl 的定制版本。

        每个控制器都有一个公共的静态 getAcls 方法:

        public static function getAcls($actionName)
        {
            $acls = array();
            $acls['roles']      = array('guest');
            $acls['privileges'] = array('index','list','view');
        
            return $acls;
        }
        

        这让其他控制器可以询问此控制器的权限。 每个控制器的 init 方法都会调用 $this->_initAcls(),它是在我自己的基本控制器中定义的:

        public function init()
        {
            parent::init(); // sets up ACLs
        }
        

        父母看起来像这样:

        public function init()
        {
            $this->_initAcls(); // init access control lists.
        }
        
        protected function _initAcls()
        {
            $to_call = array(get_class($this), 'getAcls');
            $acls = call_user_func($to_call, $this->getRequest()->getActionName());
            // i.e. PageController::getAcls($this->getRequest()->getActionName());
        
            if(isset($acls['roles']) && is_array($acls['roles']))
            {
                if(count($acls['roles'])==0)     { $acls['roles'] = null; }
                if(count($acls['privileges'])==0){ $acls['privileges'] = null; }
                $this->_helper->acl->allow($acls['roles'], $acls['privileges']);
            }
        }
        

        然后我只有一个函数叫做:

        aclink($link_text, $link_url, $module, $resource, $privilege);
        

        它调用 {$resource}Controller::getAcls() 并对它们进行权限检查。 如果他们有权限,则返回链接,否则返回 ''。

        function aclink($link_text, $link_url, $module, $resource, $privilege)
        {
            $auth = Zend_Auth::getInstance();
        
            $acl = new Acl(); //wrapper for Zend_Acl
            if(!$acl->has($resource))
            {
               $acl->add(new Zend_Acl_Resource($resource));
            }
        
            require_once ROOT.'/application/'.$module.'/controllers/'.ucwords($resource).'Controller.php';
        
            $to_call = array(ucwords($resource).'Controller', 'getAcls');
            $acls = call_user_func($to_call, $privilege);
        
            if(isset($acls['roles']) && is_array($acls['roles']))
            {
                if(count($acls['roles'])==0)     { $acls['roles'] = null; }
                if(count($acls['privileges'])==0){ $acls['privileges'] = null; }
                $acl->allow($acls['roles'], $resource, $acls['privileges']);
            }
        
            $result = $acl->isAllowed($auth, $resource, $privilege);
        
            if($result)
            {
               return '<a href="'.$link_url.'" class="aclink">'.$link_text.'</a>';
            }
            else
            {
               return '';
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-21
          • 1970-01-01
          • 2013-04-29
          相关资源
          最近更新 更多