9

我的应用程序基于 Zend 框架。我正在使用Zend_Auth身份验证,但我不确定是否Zend_Acl对我有用,因为坦率地说,我看到的示例要么过于简单,要么让我感到困惑。

我将我的应用程序中的元素视为资源,这些资源可以具有特权。包含资源特权的角色是动态定义分配给用户的。我将此信息存储在规范化表中。

  1. 用户有一个角色
  2. 一个角色可以有多个资源
  3. 资源可以有多个权限

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

这是否与 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']);
    }
}
4

1 回答 1

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 
    }
于 2010-02-17T00:08:10.877 回答