Zend ACL是否适合我的需求?

时间:2010-02-16 23:43:45

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

我的应用程序基于Zend Framework。我使用Zend_Auth进行身份验证,但我不确定Zend_Acl是否对我有效,因为坦率地说,我看到的例子对我的需求来说太简单了或者让我感到困惑。

我正在考虑将我的应用程序中的元素作为资源,这些资源可以拥有权限。包含资源权限的角色是动态定义的,分配给用户。我将这些信息存储在规范化的表格中。

  1. 用户有角色
  2. 一个角色可以有多个资源
  3. 资源可以有多个权限
  4. 角色实际上只是资源权限的集合,没有层次结构。资源的一个例子是'Page'。每个人都可以查看这些页面,但经过身份验证的用户需要“添加”,“编辑”或“删除”权限才能对页面执行任何其他操作。

    这是否与Zend ACL相连?我是否会以一种会给我带来问题的方式来思考ACL?


    我的解决方案

    Typeonerror获得了荣誉,但这是我的具体解决方案。

    我扩展了Zend_Acl以简化我的使用,因为我只加载了当前用户的角色:

    class My_Acl extends Zend_Acl
    {
        protected $_role_id;
    
        public function setRole($role_id)
        {
            $this->_role_id = $role_id;
            return $this->addRole($role_id);
        }
    
        public function getRole()
        {
            return $this->_role_id;
        }
    
        public function deny($resource, $privilege)
        {
            return parent::deny($this->_role_id, $resource, $privilege);
        }
    
        public function allow($resource, $privilege)
        {
            return parent::allow($this->_role_id, $resource, $privilege);
        }
    
        public function isAllowed($resource, $privilege)
        {
            return parent::isAllowed($this->_role_id, $resource, $privilege);
        }
    }
    

    要填充ACL,我执行一个返回resourceprivilegerole_id列的查询。如果用户的角色没有该特权,则role_id列在结果集中为空。

    $acl = new My_Acl();
    
    $auth = Zend_Auth::getInstance();
    if ($auth->hasIdentity()) {
        $userInfo = $auth->getStorage()->read();
        $acl->setRole($userInfo->role_id);
    } else {
        $acl->setRole('');
    }
    
    // QUERY HERE
    
    foreach ($privileges as $privilege) {
        if (!$acl->has($privilege['resource'])) {
            $acl->addResource($privilege['resource']);
        }
        if (is_null($privilege['role_id'])) {
            $acl->deny($privilege['resource'], $privilege['privilege']);
        } else {
            $acl->allow($privilege['resource'], $privilege['privilege']);
        }
    }
    

1 个答案:

答案 0 :(得分:10)

这正是它的工作方式,我认为你正在准确地思考它。您可以添加资源,然后添加权限以允许某些用户角色访问它们。例如,在我的CMS中,我有“开发人员”,“管理员”和“用户”。在下面的代码中,我添加了一般访问权限,然后从某些用户的访问中删除了一些操作和特定方法。当然这对我的应用来说非常具体,但基本上,你必须从auth-> getIdentity()(或类似的)获取用户的角色,然后从数据库中添加你的角色/资源。

<?php

/**
 * @author     Benjamin Borowski <ben.borowski@typeoneerror.com>
 * @copyright  Copyright (c) Typeoneerror Studios http://typeoneerror.com
 * @version    $Id$
 * @category   Typeoneerror
 * @package    Acl
 */

/**
 * Defines basic roles and resources for an application as
 * well as a Content Management System (CMS).
 *
 * Zend_Acl provides a lightweight and flexible access control list
 * (ACL) implementation for privileges management.
 *
 * {@inheritdoc}
 *
 * @author     Benjamin Borowski <ben.borowski@typeoneerror.com>
 * @copyright  Copyright (c) Typeoneerror Studios http://typeoneerror.com
 * @version    $Id$
 * @category   Typeoneerror
 * @package    Acl
 */
class Typeoneerror_Acl extends Zend_Acl
{
    /**
     * Constructor function.
     *
     * Creates basic roles and resources and adds them to Acl.
     *
     * {@inheritdoc}
     *
     * @return Typeoneerror_Acl
     */
    public function __construct()
    {
        //---------------------------------------
        // ROLES
        //---------------------------------------

        $this->_addRole("guest")
             ->_addRole("member", "guest")
             ->_addRole("admin", "member")
             ->_addRole("developer", "admin");

        //---------------------------------------
        // FRONT-END RESOURCES
        //---------------------------------------

        $this->_add("default");

        //---------------------------------------
        // BACK-END RESOURCES
        //---------------------------------------

        $this->_add("cms")
             ->_add("cms:articles", "cms")
             ->_add("cms:auth", "cms")
             ->_add("cms:bug-report", "cms")
             ->_add("cms:calendar", "cms")
             ->_add("cms:categories", "cms")
             ->_add("cms:comments", "cms")
             ->_add("cms:error", "cms")
             ->_add("cms:galleries", "cms")
             ->_add("cms:pages", "cms")
             ->_add("cms:photos", "cms")
             ->_add("cms:tags", "cms")
             ->_add("cms:users", "cms");

        //---------------------------------------
        // GUEST PERMISSIONS
        //---------------------------------------

        $this->allow("guest", "default")
             ->allow("guest", "cms:auth")           // -- guests can attempt to log-in
             ->allow("guest", "cms:error")          // -- guests can break stuff
             ->allow("guest", "cms:bug-report");    // -- guests can report bugs

        //---------------------------------------
        // ADMIN PERMISSIONS
        //---------------------------------------

        $this->allow("admin")
             ->deny("admin", null, "purge")                       // -- admins cannot purge (normally)
             ->deny("admin", "cms:comments", "create");           // -- only devs can create a comment

        //---------------------------------------
        // DEVELOPER PERMISSIONS
        //---------------------------------------

        $this->allow("developer");             // -- unrestricted access

        return $this;
    }

    /**
     * Adds a Resource having an identifier unique to the ACL.
     *
     * @param Zend_Acl_Resource_Interface $resource       The resource to add
     * @param Zend_Acl_Resource_Interface|string $parent  A parent resource it inherits from
     * @return Typeoneerror_Acl                           Reference to Acl class
     */
    protected function _add($resource, $parent = null)
    {
        $this->add(new Zend_Acl_Resource($resource), $parent);

        return $this;
    }

    /**
     * Wrapper for <code>addRole</code>
     *
     * @param Zend_Acl_Resource_Interface $resource        The resource to add
     * @param Zend_Acl_Resource_Interface|string $parents  Parent resources it inherits from
     * @return Typeoneerror_Acl                            Reference to Acl class
     */
    protected function _addRole($role, $parents = null)
    {
        $this->addRole(new Zend_Acl_Role($role, $parents));

        return $this;
    }

}

修改

猜猜我还应该解释一下,我有一个Typeoneerror_Controller_Plugin_Acl,无论何时请求任何资源。在这里,我创建了所请求资源的“标记”,并检查用户是否有权访问该标记:

    $controller = $request->controller;
    $action = $request->action;
    $module = (empty($request->module)) ? "default" : $request->module;

    // -- this ends up like "cms:articles" just like my resources
    $resource = $module . ":" . $controller;

    if (!$this->__acl->has($resource))
    {
        $resource = $module;
    }

    // -- the good stuff. check if the user's role can access the resource and action
    if (!$this->__acl->isAllowed($role, $resource, $action))
    {
        //more code 
    }