CakePHP中文手册【翻译】-ACL

访问控制列表(ACL

1

理解ACL如何工作

最重要,也最强大的事情是需要一系列的访问控制。访问控制列表是一种细粒度,易维护以及易管理的方式来管理应用程序权限。访问控制列表或ACL[1]处理2件主要的事情:他们想要的事情,以及想要他们的事情。按照ACL的行话来说,事情想要的使用的原料(最常见的是用户)称为访问请求对象,或者AROAccess Request Object)。这些实体之所以称为'对象',是因为有的时候请求的对象不是一个人-有的时候你可能想限制访问某个Cake Controller,而此Controller在应用程序的其它部分不得不初始化逻辑。ACO可以是你想控制的任何东西,从一个Controller动作,到一个Web Service,或到一个你祖母的在线日记上去。

为了即刻使用所有的缩写形式,可以如下:ACL是用来决定一个ARO什么时候可以访问一个ACO

现在,为了帮助你理解它,让我们使用一个实际的例子吧。假想一下,再过一会,一个冒险家们使用的计算机系统。这组冒险家的老大在为其他人员维护一个正常程度的隐私和安全时,他又想继续处理他们的请求。其中涉及到的ARO如下:

Gandalf
Aragorn
Bilbo
Frodo
Gollum
Legolas
Gimli
Pippin
Merry

这些就是系统里的实体,他们会请求系统的东西(ACO)。你应该注意到ACL并“不是”一个系统,它的意思是指认证的用户。你也应该有一种方式来存储用户信息,而且当用户进入系统时,能够验证他们的身份。一旦你知道用户是谁时,这就是ACL真正发光之处!OK,还是让我们回到冒险家那里吧。

Gandalf需要做的下一件事情是制作一个系统会处理的东西(ACO)的初始化列表.他的列表可能如下:

武器(Weapon
环(Ring
咸肉(Salted Pork
外交策略(Diplomacy
啤酒(Ale

传统上,我们会使用一组矩阵来管理系统,此矩阵展示了一组用户和与之相关对象的权限。如果此信息存储在一个表里,它可能会像下面这样,其中X表示拒绝访问,O代表允许访问:

          武器                       咸肉        外交策略      啤酒
Gandalf     X           X              O              O            O
Aragorn     O           X              O              O            O
Bilbo       X           X              X              X            O
Frodo       X           O              X              X            O
Gollum      X           X              O              X            X
Legolas     O           X              O              O            O
Gimli       O           X              O              X            X
Pippin      X           X              X              O            O
Merry       X           X              X              X            O

让我们看第一眼,看起来这组系统工作得非常出色。这里的分配可以保护安全(只有Frodo可以使用环),并且可以保护突发事件(让Hobbit得不到咸肉)[2]。他们读起来看似已经足够细致,足够容易,真的吗?

对于像这样的一个小型系统,也许一个矩阵就可以完成。但是对于一个逐步增长的系统或者一个带有大数量的资源(ACO)和用户(ARO)的系统来说,一个表格可能变得笨重,而不是变得快捷。例如,假设我们打算想控制对几百个战争驻扎地的访问,以及试图按单元管理他们。矩阵的另外一个缺点是你不会真正的按逻辑将这些用户分组,或者对已按逻辑分组的用户做出一连串的权限变化。例如,一旦战争结束,它肯定会很好的自动允许Hobbit访问啤酒和猪肉:当对所有‘Hobbit'做出一连串权限改变很容易时,实现一个基于独立用户的基本原则则是令人乏味的,也是有错误倾向的。

以树结构实现ACL是最常见的。通常有一个ARO树和ACO树。通过将他们以树结构组织,权限仍然可以以细粒度来处理,但也可以很好的保持对大蓝图的把握。作为一个英明的老大,在他的新系统里,Gandalf选择使用ACL,并将他的对象像下面一样进行组织:

环的团体关系:
战士
    Aragorn
    Legolas
    Gimli
指挥家
    Gandalf
Hobbit
    Frodo
    Bilbo
    Merry
    Pippin
访问者
    Gollum

按这种方式建立我们团体,我们可以定义树的访问控制,并将这些权限应用到任何子节点中。缺省的权限是拒绝访问任何东西。与你处理树的方式一样,挑选一些权限并使用他们,最后应用的权限(将它应用到你正想知道的ACO上)就是你保持的那一个,因此,使用我们的ARO树,Gandalf可以出挂起一些权限:

环的团体关系: [Deny: ALL]
    战士               [Allow: Weapons, Ale, Elven Rations, Salted Pork]
        Aragorn
        Legolas
        Gimli
    指挥家             [Allow: Salted Pork, Diplomacy, Ale]
        Gandalf
    Hobbit             [Allow: Ale]
        Frodo
        Bilbo
        Merry
        Pippin
    访问者              [Allow: Salted Pork]
        Gollum

如果你想使用ACL查看是否允许Pippin访问啤酒,我们先得获取他在树上的路径,即Fellowship->Hobbits->Pippin.然后我们得看看依附在这些节点上的不同权限,并使用与Pinppin和啤酒相关的最具体的权限。

1.      Fellowship = DENY Ale,拒绝(因为它被设置为拒绝所有ACO

2.      Hobbits = ALLOW Ale, 允许

3.      Pippin = ?;确实不存在任何指定的啤酒信息,因此我们可以为ALLOW

4.      最后结果: 允许啤酒.

树也允许我们对更细粒度的控制做出更好的调整,但同时仍然可以保持对ARO组做出交替的变化:

Fellowship of the Ring: [Deny: ALL]
    Warriors                [Allow: Weapons, Ale, Elven Rations, Salted Pork]
        Aragorn             [Allow: Diplomacy]
        Legolas
        Gimli
    Wizards                 [Allow: Salted Pork, Diplomacy, Ale]
        Gandalf
    Hobbits                 [Allow: Ale]
        Frodo               [Allow: Ring]
        Bilbo
        Merry               [Deny: Ale]
        Pippin              [Allow: Diplomacy]
    Vistors                 [Allow: Salted Pork]
        Gollum

你从中可以看到它,是因为Aragorn ARO的维护与于其他战士ARO组类似,但是当你看到合适时,你仍然可以做出好节奏的调整以及特殊的情况。同样,权限确实为DENY,仅向下遍历树的变化强制为一个ALLOW。为了看看Merry是否可以访问啤酒(Ale),我们需要查找他在树上的路径:Fellowship->Hobbits->Merry,并沿此路径向下工作,同时追踪与ale相关的权限:

1.    Fellowship = DENY (因为它设置为拒绝所有), 因此拒绝ale

2.    Hobbits = ALLOW: ale,允许ale

3.    Merry = DENY ale,因此拒绝ale

4.    最终结果: 拒绝ale

2

定义权限:基于INICake ACL

Cake的第一个ACK实现是基于INI文件,此文件存储在Cake安装目录下面。由于它的实用性以及稳定性,我们建议你使用数据库存储ACL的解决方案,因为它具有可以在空中创建新ACOARO的能力。在简单的应用程序中,因为它的用途我们推荐它-并且特别是对那些因为某些原因而没有使用数据库的家伙们。

ARO/ACO权限在/app/config/acl.ini.php中指定。指定访问权限的指令可以在acl.ini.php文件的开头找到:

; acl.ini.php - Cake ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)
; aro = access request object (something requesting access)
;
; User records are added as follows:
;
; [uid]
; groups = group1, group2, group3
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; Group records are added in a similar manner:
;
; [gid]
; allow = aco1, aco2, aco3
; deny = aco4, aco5, aco6
;
; The allow, deny, and groups sections are all optional.
; NOTE: groups names *cannot* ever be the same as usernames!

 

通过使用INI文件,你也应指定用户(ARO),他们属于的组,以及他们自己拥有的权限。你也指定带有权限的组。为了学习如何利用INI文件使用CakeACL组件来检验权限,参看11.4这节。

3

定义权限: Cake的数据库ACL

开始

ACL权限的实现缺省的是数据库存储。数据库ACL,或者dbACL,由一组核心的model,以及一个命令行脚本组成,此命令行脚本在Cake安装时而产生。Cake使用model与你的数据库进行交互,这样做的目的是为了存储和获取ACL树上的节点。使用命令行脚本有助于你开始与你的树进行交互。

为了开始,首先需要保证/app/config/database.php存在,并且正确的配置它。对于一个Cake的新安装,告诉它这些最简单的方法就是使用一个web浏览器来完成安装。如果你正确安装,在离页面顶端之处,你应该可以看到信息"Your database configuration file is present." 以及 "Cake is able to connect to the database."参看4.1节获取更多关于数据库配置的的信息。

下一步,使用ACL命令行脚本初始化你的数据库来存储ACL信息。/cake/scripts/acl.php 的脚本帮助你完成它。执行下面的命令(来自/cake/scripts/目录)为ACL初始化你的数据库。

使用acl.php初始化数据库

$ php acl.php initdb

Initializing Database...
Creating access control objects table (acos)...
Creating access request objects table (acos)...
Creating relationships table (aros_acos)...

Done.

 

在这里,你应该可以检查你项目的数据库是否有新表。如果你正奇怪Cake如何将树的信息存储在这些表里,研读一下修改的数据库树遍历。基本上,它存储了节点,以及他们在树中的位置。

aros数据库表存储了他们各自树的节点信息,aros_acos表用来将ARO链接到他们可以访问的ACO

现在,你应该可以创建AROACO树了。

创建AROACO

引用ARO/ACO2种方法,一种是给他们一个数字型的ID,它常常是他们属于的那个表的主键。另外一种方法是给他们一个字符串别名。这2种方法不会相互排斥。

定义Aro_Cake model可以创建一个新的AROAro类的create()方法有3个参数:link_id, $parent_id,以及$alias。此方法创建一个在parent_id指定的父对象之下的ACL对象,或者是如果传入的$parent_idnull,作为一个根对象。$link_id允许你将当前用户对象链接到CakeACL结构。别名参数允许你放入一个非整型ID的对象。

在你能够创建ACOARO之前,我们需要加载这些类。实现加载的最简单方法是使用$components数组,并将Cake ACL组件包含在Controller里:

var $components = array('Acl');

一旦完成,我们看看这些对象的创建实例是什么样子。可以把下面的代码放在一个Controller的动作中:

$aro = new Aro();

// First, set up a few AROs.
// These objects will have no parent initially.

$aro->create( 1, null, 'Bob Marley' );
$aro->create( 2, null, 'Jimi Hendrix');
$aro->create( 3, null, 'George Washington');
$aro->create( 4, null, 'Abraham Lincoln');

// Now, we can make groups to organize these users:
// Notice that the IDs for these objects are 0, because
//     they will never tie to users in our system

$aro->create(0, null, 'Presidents');
$aro->create(0, null, 'Artists');

//Now, hook AROs to their respective groups:

$aro->setParent('Presidents', 'George Washington');
$aro->setParent('Presidents', 'Abraham Lincoln');
$aro->setParent('Artists', 'Jimi Hendrix');
$aro->setParent('Artists', 'Bob Marley');

//In short, here is how to create an ARO:
$aro = new Aro();
$aro->create($user_id, $parent_id, $alias);

 

你也可以利用使用了$acl.php的命令行脚本创建ARO,创建的ARO<link_id> <parent_id>  <alias>.

以类似的方法创建ACO

$aco = new Aco();

//Create some access control objects:
$aco->create(1, null, 'Electric Guitar');
$aco->create(2, null, 'United States Army');
$aco->create(3, null, 'Fans');

// I suppose we could create groups for these
// objects using setParent(), but we'll skip that
// for this particular example

//So, to create an ACO:
$aco = new Aco();
$aco->create($id, $parent, $alias);

 

相应的命令行脚本命令可能是:$acl.php 创建ACO <link_id> <parent_id> <alias>.

分配权限

A在创建ACOARO后,最后我们可以分配2个组之间的权限。使用Cake的核心组件来完成。让我们继续我们的例子吧:

// First, in a controller, we'll need access
// to Cake's ACL component:

class SomethingsController extends AppController
{
    // You might want to place this in the AppController
    // instead, but here works great too.

    var $components = array('Acl');

    // Remember: ACL will always deny something
    // it doesn't have information on. If any
    // checks were made on anything, it would
    // be denied. Let's allow an ARO access to an ACO.

    function someAction()
    {
        //ALLOW

        // Here is how you grant an ARO full access to an ACO
        $this->Acl->allow('Jimi Hendrix', 'Electric Guitar');
        $this->Acl->allow('Bob Marley',   'Electric Guitar');

        // We can also assign permissions to groups, remember?
        $this->Acl->Allow('Presidents', 'United States Army');

        // The allow() method has a third parameter, $action.
        // You can specify partial access using this parameter.
        // $action can be set to create, read, update or delete.
        // If no action is specified, full access is assumed.

        // Look, don't touch, gentlemen:
        $this->Acl->allow('George Washington', 'Electric Guitar', 'read');
        $this->Acl->allow('Abraham Lincoln',   'Electric Guitar', 'read');

        //DENY

        //Denies work in the same manner:

        //When his term is up...
        $this->Acl->deny('Abraham Lincoln', 'United States Army');


    }
}
 

这个特殊的controller并不是特别有用,但是它会向你展示它们工作的过程。使用和你的用户管理controller相连的Acl组件会是一个最好的使用方法。系统一旦创建了一个用户,就会创建它的ARO,并将它放到树的正确位置,而且将权限分配到基于它的身份的特定的ACOACO组中去。

也可以使用与Cake一起打包的命令行脚本分配权限。此语法和model函数有些类似,而且可以通过执行$php acl.php帮助来查看它。

4

检验权限:ACL组件

检验权限是Cake ACL最简单的一部分:它包括使用一个Acl组件中的简单方法:check().在你的应用程序中实现ACL的一个优秀方法是将动作放在AppController里,此Controller会完成ACL检验。一旦把它放在那里,你就可以访问Acl组件,并完成应用程序级的权限检验。这里是实现的实例:

class AppController extends Controller
{
    // Get our component
    var $components = array('Acl');

    function checkAccess($aco)
    {
        // Check access using the component:
        $access = $this->Acl->check($this->Session->read('user_alias'), $aco, $action = "*");

        //access denied
        if ($access === false)
        {
            echo "access denied";
            exit;
        }
        //access allowed
        else
        {
            echo "access allowed";
            exit;
        }
    }
}

 

基本上,通过在AppController里使Acl组件可用,它将在应用程序中的任何Controller中都可见。

// Here's the basic format:
$this->Acl->Check($aro, $aco, $action = '*');

 



[1]因为ACL直观明了,在后面都将采用ACL,以后不再说明

[2] 译者注:Hobbit是英国作家J.R.R.Tolkien笔下创造的生性善良平和的穴居矮人。请访问www.tolkiensociety.org

Last Updated:2006-12-03
posted @ 2006-11-28 23:24  张太国  阅读(...)  评论(...编辑  收藏