简体   繁体   English

Zend ACL是否适合我的需求?

[英]Does Zend ACL suit my needs?

I have based my application upon the Zend Framework. 我的应用程序基于Zend Framework。 I am using Zend_Auth for authentication, but I'm not sure if Zend_Acl will work for me because, frankly, the examples I've seen are either too simplistic for my needs or confuse me. 我使用Zend_Auth进行身份验证,但我不确定Zend_Acl是否适合我,因为坦白说,我看到的例子对我的需求来说太简单了或者让我感到困惑。

I'm thinking of elements in my application as Resources and these Resources can have have Privileges. 我正在考虑将我的应用程序中的元素作为资源,这些资源可以拥有权限。 Roles containing Resource Privileges are dynamically defined assigned to users. 包含资源权限的角色是动态定义的,分配给用户。 I'm storing this information in normalized tables. 我将这些信息存储在规范化表格中。

  1. Users have a Role 用户有角色
  2. A Role can have multiple Resources 角色可以有多个资源
  3. Resources can have multiple Privileges 资源可以具有多个权限

Roles are really just collections of Resource Privileges with no hierarchy. 角色实际上只是资源权限的集合,没有层次结构。 An example of a Resource would be 'Page'. 资源的一个例子是'Page'。 Everyone can view the pages, but a authenticated user would need 'add', 'edit', or 'delete' privileges to do anything else with pages. 每个人都可以查看页面,但经过身份验证的用户需要“添加”,“编辑”或“删除”权限才能对页面执行任何其他操作。

Does this mesh with Zend ACL? 这与Zend ACL相匹配吗? Am I thinking ACL in a way that's going to create problems for me? 我是否会以一种会给我带来问题的方式思考ACL?


My Solution 我的解决方案

Typeonerror gets the credit, but here's my specific solution. Typeonerror获得了荣誉,但这是我的具体解决方案。

I extended Zend_Acl to simplify my usage because I only load the role of the current user: 我扩展了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);
    }
}

To populate the the ACL I execute a query which returns resource , privilege , and role_id columns. 要填充ACL,我执行一个返回resourceprivilegerole_id列的查询。 The role_id column is null in the result set if the user's role does not have that privilege. 如果用户的角色没有该特权,则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']);
    }
}

That's exactly how it works and I think you're thinking about it in an accurate way. 这正是它的工作方式,我认为你正在准确地思考它。 You can add your resources and then add privileges to allow certain user roles to access them. 您可以添加资源,然后添加权限以允许某些用户角色访问它们。 For example, in my CMS, I have "developers", "admins", and "users". 例如,在我的CMS中,我有“开发人员”,“管理员”和“用户”。 In the code below I add general access and then remove some actions and specific methods from certain user's access. 在下面的代码中,我添加了一般访问权限,然后从某些用户的访问中删除了一些操作和特定方法。 Of course this is pretty specific to my application but basically, you'd have to get the user's role from auth->getIdentity() (or similar) and then add your roles/resources from the database. 当然这对我的应用程序非常具体,但基本上,你必须从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;
    }

}

Edit 编辑

Guess I should also explain that I have an Typeoneerror_Controller_Plugin_Acl which is used whenever any resource is requested. 猜猜我还应该解释一下,我有一个Typeoneerror_Controller_Plugin_Acl ,只要请求任何资源就会使用它。 Here I create the "tag" that the requested resource makes and check whether the user has access to that tag: 在这里,我创建了所请求资源的“标记”,并检查用户是否有权访问该标记:

    $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 
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM