Zend Framework:如何在一个页面上显示多个操作,每个操作都需要不同的授权级别

时间:2009-01-23 16:28:28

标签: zend-framework

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

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

我的问题是:在控制器,操作,视图和布局方面,这个界面的最佳架构是什么?

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

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

干杯。

3 个答案:

答案 0 :(得分:1)

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

  1. 您可以使用循环(或硬编码块)加载每个表单。
  2. 在每个表单对象的构造函数中,可能会抛出一个自定义异常,可以捕获并妥善处理。
  3. Zend_Form扩展名的构造函数中扩展所有自定义Form对象(可能是最好的方法,因为它有助于减少代码重复)。
  4. 请记住,如果您使用ZF执行更新的AJAXy解决方案,您的控制器也需要在其init()方法中运行ACL检查,以防止对您的数据库进行未经授权的更改。

    希望有所帮助。

答案 1 :(得分:0)

你有没有解决这个问题?

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

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

答案 2 :(得分:-1)

我使用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 '';
    }
}