基于模块的应用程序中的ZEND_ACL解决方案

时间:2013-01-31 16:10:19

标签: zend-framework zend-auth zend-acl zend-framework-modules

我正在开发ZF上的应用程序。

我遇到了一个巨大的无法解决的问题 - ZEND_Acl

这对我来说无法解决,因为我找到的每篇文章都与基于MODULE的应用程序无关。

最近我发现packtpub article描述了在模型中使用ACL

但它看起来很复杂,很复杂,而不是我一直在寻找的那个。

它有StoreFront - 一切都在那里,在我的情况下,我将所有内容分成模块。

我在许多其他来源和文档中都看到了ACL实现技术。

我无法弄清楚如何解决以及从何处开始(实际上是如何)开发/构建我的ACL实现。

我的应用程序如下所示:

application/ 
       configs/
       layouts/
               master.phtml
               admin.phtml
       modules/
               users/
                    controllers/
                                adminController
                                indexContoller
                    models/
                    views/
               blog/
                    controllers/
                                adminController
                                indexController
                    models/
                    views/
               orders/
                    controllers/
                                adminController
                                indexController
                    models/
                    views/

正如您所看到的,我在adminControllers和indexControllers中的前端功能中有管理功能。

在模块内部使用adminControllers和视图的想法是使用分散的模块体系结构,而不是为管理员创建单独的模块。

现在我想为我的应用程序实现ACL。

通常我会有管理员 - superadmin,编辑,发布商 - 管理员,它们将访问所有adminControllers,但每个action,并且肯定用户无法访问adminControllers。

和用户 - 访客,已注册,付费,因此层次结构看起来像这样:

$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('visitor')); 
$acl->addRole(new Zend_Acl_Role('registered'), 'visitor');
$acl->addRole(new Zend_Acl_Role('paid'), 'registered');
$acl->addRole(new Zend_Acl_Role('publisher'), 'paid');
$acl->addRole(new Zend_Acl_Role('editor'), 'publisher');
$acl->addRole(new Zend_Acl_Role('superadmin'), 'editor');  

此层次结构可以跨应用程序使用。

目标是在每个模块中写入写权限和资源,这样我就可以避免在特定项目中不存在某个模块的情况下在ACL文档中使用垃圾。

我还没有在YouTube上测试Alexander Romanenko教程的方法,但在开发ACL时,他正在从FrontController插件加载ACL - 在我的情况下会采用什么方法?

在实施ACL时,我必须考虑ACL Dynamic Assertions以确保将来使用。像“访客”这样的时刻无法发表评论,注册用户也无法在博客中看到PAID文章。

也许你可以帮助我将ACL集成到我的项目中,也许你知道很好的资源在哪里找到HOW TO并遵循说明。

修改

具有ACL的preDispatch()的Controller插件将用于每个模块(在本例中为USERS)(对吗?)

我尝试在Module的(USERS)Bootstrap中自动加载插件:

$plugin = Zend_Controller_Front::getInstance();
$plugin->registerPlugin(new Users_Plugin_AccessCheck());

但似乎它需要整个应用程序的这个插件并给出错误:

Fatal error: Uncaught exception 'Zend_Session_Exception' with message 'Session must be started before any output has been sent to the browser; output started in H:\Server\xampp\htdocs\c2g\application\modules\users\plugins\AccessCheck.php/6' in H:\Server\xampp\htdocs\c2g\library\Zend\Session.php:451 Stack trace: #0 ... So on

我认为这是因为插件加载了两次。但是除了模块(USERS)本身之外,每个页面都会发生这种情况。

1 个答案:

答案 0 :(得分:1)

我在我的一个应用程序中使用了类似的结构,所以希望我可以指出你正确的方向。我设置的方式是:

  • 角色在我的主应用程序引导程序中初始化(这是您在问题中包含的代码),将Zend_Acl对象存储在注册表中以便于在其他地方访问
  • 每个模块引导程序都会设置自己的ACL资源,并定义哪些角色可以访问哪些
  • 使用控制器插件完成ACL检查。

资源名称只是任意字符串,因此只要遵守约定,就可以在插件中自动执行ACL检查。例如,假设您所需要的是每个模块的索引和管理控制器的资源。在每个模块引导程序中,您都有类似这样的内容:

protected function _initAcl()
{
    $acl = Zend_Registry::get('acl');

    $frontendResource = new Zend_Acl_Resource('users');
    $adminResource = new Zend_Acl_Resource('users-admin');

    $acl->addResource($frontendResource);
    $acl->addResource($adminResource);

    // allow everyone frontend access
    $acl->allow('visitor', $frontendResource);

    // admins only for admin access
    $acl->allow('superadmin', $adminResource);
}

然后在ACL控制器插件中,通过检查请求对象并执行检查来计算资源名称:

public function preDispatch(Zend_Controller_Request_Abstract $request)
{
    $acl = Zend_Registry::get('acl');

    $currentResource = $request->getModuleName().'-'.$request->getControllerName();
    if ($acl->has($currentResource) && !$acl->isAllowed($user->role, $currentResource)) {
        // permissions error
    }
}