简介Zend_Acl 为权限管理提供轻量并灵活的访问控制列表 (ACL,access control list) 的实现。一般地,应用软件可以利用这样的功能限制某些特定对象来访问特定保护的对象。 在本文档中,
通过规范和访问控制列表(ACL)的使用,应用软件可以控制角色(roles)如何来访问资源(resources)。 关于资源(Resource)
在 Zend_Acl 中,创建一个 resource 非常简单。Zend_Acl 提供了 resource
接口 Zend_Acl 提供了一个树结构,它可以添加多个 resources (或者叫“访问控制下的区域”)。因为 resources 被存储在这样一个树结构, 所以它们可以被组织成从一般(树根)到特殊(树叶)。基于特殊resource的查询将自动从resource的等级结构中搜索分配给祖先rResources的规则, 它允许简单的规则继承。例如,要把一个缺省的规则应用到一个城市的每个建筑物,就简单地把这个规则分配给这个城市, 而不是把规则分配给每个建筑物。然而,有些建筑物也许要求例外的规则,在Zend_Acl里,很容易地通过分配例外规则给每个有这样要求的建筑物来实现。 一个 resource 可以从唯一的一个父 resource 继承,而这个父 resource 也有它自己的父 resource,等等。 Zend_Acl 也支持基于 resources 的权限(例如:"create", "read", "update", "delete"), 所以开发者可以根据 resource 分配影响全部或者特殊权限的规则到一个或多个资源。 关于角色(Role)
象 Resources 一样,创建一个 role 也非常简单。 Zend_Acl 提供了 在 Zend_Acl, 一个 role 可以从一个或多个 role 继承,这就是在 role 中支持规则的继承。例如,一个用户 role,如 “sally”, 可以属于一个或多个 role,如:“editor”和“administrator”。开发者可以分别给“editor”和“administrator”分配规则, 而“sally”将从它们俩继承规则,不需要直接给“sally”分配规则。 虽然从多重角色继承的能力非常有用,但是多重继承也带来了一定程度的复杂性。下面的例子来示例含糊情形和Zend_Acl如何解决它。 Example #1 角色之间的多重继承
下面的代码定义了三个基本角色 - "
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('guest'))
->addRole(new Zend_Acl_Role('member'))
->addRole(new Zend_Acl_Role('admin'));
$parents = array('guest', 'member', 'admin');
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);
$acl->add(new Zend_Acl_Resource('someResource'));
$acl->deny('guest', 'someResource');
$acl->allow('member', 'someResource');
echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';
因为没有明确地为 "
如果Zend_Acl打算继续检查为父角色所定义的规则,然而,
它将发现"
Zend_Acl 解决了这个模棱两可的问题,当它发现第一个可用的规则时,就完成了查询。
对于这个案例,因为"
创建访问控制列表(ACL)ACL 可以表示任何一组物理或虚拟对象,然而,作为示范,我们将创建一个基本的内容管理系统的(CMS)ACL, 在一个范围很宽的多样化区域里,它将维护若干个等级的组。为创建一个新的 ACL 对象,我们不带参数地实例化这个 ACL:
$acl = new Zend_Acl();
注册角色(Role)CMS 通常需要一个分级的权限系统来决定它的用户的授权能力。 作为示范,“Guest”组允许有限的访问,“Staff”适合大多数的执行日常操作的CMS用户,“Editor”组适合于发布、复核、存档和删除内容, 最后“Administrator”组的任务包括所有其它组的内容并包括敏感的信息、用户管理、后台配置数据和备份/导出。 这组许可可以被表示为一个 role 注册表,允许每个组从“”组继承权限,也可以为单一的组提供独特的权限。这些许可可以表示如下:
对于这个范例,
$acl = new Zend_Acl();
// 用 Zend_Acl_Role 把组添加到 Role 注册表
// Guest 不继承访问控制
$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);
// Staff 从 guest 继承
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
/*
另外, 上面的也可这样来写:
$acl->addRole(new Zend_Acl_Role('staff'), 'guest');
*/
// Editor 从 staff 继承
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');
// Administrator 不继承访问控制
$acl->addRole(new Zend_Acl_Role('administrator'));
定义访问控制现在 ACL 包含了相关的 roles,可以建立规则来定义 roles 如何访问 resources。 你也许注意到我们在这个范例里没有定义任何特定的 resources, 这简单地表示这些规则适用于所有 resources。 Zend_Acl 提供一个实现,籍此,规则只需要被分配从一般到特殊,最小化规则的需求,因为 resources 和 roles 继承由它们祖先定义的规则。
因此,我们可以用最少量的代码来定义适度复杂的规则。应用上面定义的基本许可:
$acl = new Zend_Acl();
$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');
$acl->addRole(new Zend_Acl_Role('administrator'));
// Guest 只可以浏览内容
$acl->allow($roleGuest, null, 'view');
/*
另外, 上面也可写为:
$acl->allow('guest', null, 'view');
*/
// Staff 从 guest 继承浏览权限,但也要另外的权限
$acl->allow('staff', null, array('edit', 'submit', 'revise'));
// Editor 从 Staff 继承 view, edit, submit 和 revise 权限
// 但也要另外的权限
$acl->allow('editor', null, array('publish', 'archive', 'delete'));
// Administrator 不需要继承任何权限,它拥有所有的权限
$acl->allow('administrator');
在上面 查询 ACL
我们现在有一个灵活的 ACL 可以用来决定请求者在整个 web 应用里是否拥有执行功能的许可。用
echo $acl->isAllowed('guest', null, 'view') ?
"allowed" : "denied";
// allowed
echo $acl->isAllowed('staff', null, 'publish') ?
"allowed" : "denied";
// denied
echo $acl->isAllowed('staff', null, 'revise') ?
"allowed" : "denied";
// allowed
echo $acl->isAllowed('editor', null, 'view') ?
"allowed" : "denied";
// allowed because of inheritance from guest
echo $acl->isAllowed('editor', null, 'update') ?
"allowed" : "denied";
// denied because no allow rule for 'update'
echo $acl->isAllowed('administrator', null, 'view') ?
"allowed" : "denied";
// allowed because administrator is allowed all privileges
echo $acl->isAllowed('administrator') ?
"allowed" : "denied";
// allowed because administrator is allowed all privileges
echo $acl->isAllowed('administrator', null, 'update') ?
"allowed" : "denied";
// allowed because administrator is allowed all privileges
|