如何在CakePHP1.2中使用ACL(译)

第一篇翻译下来的教程,花不了什么时间。Google先翻译,然后我润笔而已并对实际状态做了修改。润得不好,大家多包涵,将就着看了。其实还是看英文舒服。先译出来,然后我还要自己调试一下看看。
转载请遵循我的CC协定。

原文出处:How to use ACL with Cake PHP 1.2.x?

这篇教程将简短地向你介绍如何在Cakephp 1.2.x中使用Acl。我曾经在这上面花了大量的时间,但在Gwoo、AD7Six还有其它朋友的帮助下,加上一些的调试及源代码的阅读,我写出了这篇教程。

在开始之前,我想你应该有一些ACL的基本概念以及它应该用在什么地方。如果你对这些不甚了解的话,请阅读http://manual.cakephp.org/chapter/acl

首先你应该通过在命令行下输入这行命令来创建ACL所需要的数据库
cake acl initdb

现在,我们将初始化一些更高级别的aro和aco设置。你也可以通过控制台命令来运行。不过,我更喜欢通过controller来运行,并没有什么特别,照着做就好了!

Aros (可以是用户或是某项服务等)是一个要求访问Acos(可以是controller,action或其它服务)的东西。但在这个例子里,我们将限制Aros作为users,而把Acos作为controllers。我们将设置以下Aros(用户) :

  1. Admin
  2. |–>User::1
  3. User
  4. Guest

据你的需求,你
可以增加更多的用户类别,但我们目前只谈论最简单的状态。Admin,User和Guest是一个用户组,而实际每个用户将属于其中的用户组。
‘User::1’代表着一个用户id为1的用户。我们定义用户id为1的用户是admin下的一个实际用户,该用户会继承所有管理员的权限。这么做是没
有必要的,但是,你如果确定你的系统中至少有一个用户是管理员,那么,为什么不在这时候做这个操作呢。当然,这个用户的id是多少应该由你的系统具体情况
来决定。

我们还将创建以下的Acos,也就是controllers

  1. User
  2. Post

我们将添加两个acos,’User’和’Post’。但现在,你认为如果Acos是一个controller, 那么为什么不根据controller的命名规
则,命名为复数的’Posts’,而是’Post’?好问题。这是因为通常一个controller的动作,可分为四种类型的动作:’创建
Create’,
‘读取Read’,’更新Update’或’删除Delete’。而这四个动作是针对对model中的单个记录或一组记录的。因此,我们的操作是基于记录
层面的访问控制(Access
Control)。我们希望确定当前的Aro(一个User)是否对一个Aco(比如一个Post的记录)有权限进行’C’, ‘R’,
‘R’或’D’的操作。如果有权限,就允许该Aro进行操作,否则就拒绝操作。以下代码,就列出了手工创建刚刚我们所讨论的Aro和Aco。

Controller Class:

<?php 

class InitAclController extends AppController

{

  var 
$name 'InitAcl';

  var 
$components = array('Acl');

  var 
$uses = array();

  function setupAcl()

  {

    
$aro = $this->Acl->Aro;

    $aro->create();

    
$aro->save(array(

      
'model'=>'User',

      
'foreign_key'=>null,

      
'parent_id'=>null,

      
'alias'=>'Admin'));

    $aro->create();

    
$aro->save(array(

      
'model'=>'User',

      
'foreign_key'=>null,

      
'parent_id'=>null,

      
'alias'=>'User'));

    $aro->create();

    
$aro->save(array(

      
'model'=>'User',

      
'foreign_key'=>null,

      
'parent_id'=>null,

      
'alias'=>'Guest'));

    $parent $aro->findByAlias('Admin');

    
$parentId $parent['Aro']['id'];    

    $aro->create();

    
$aro->save(array(

      
'model'=>'User',

      
'foreign_key'=>1,

      
'parent_id'=>$parentId,

      
'alias'=>'User::1'));

    

    

    $aco = $this->Acl->Aco;

    
$aco->create();

    
$aco->save(array(

       
'model'=>'User',

       
'foreign_key'=>null,

       
'parent_id'=>null,

       
'alias'=>'User'));

       

    
$aco->create();

    
$aco->save(array(

       
'model'=>'Post',

       
'foreign_key'=>null,

       
'parent_id'=>null,

       
'alias'=>'Post'));

  

   
// Give admin full control over acos 'User' & 'Post'

   
$this->Acl->allow('Admin''User''*');

   
$this->Acl->allow('Admin''Post''*');

   // Give the user group only create & read access for 'Post' 

   
$this->Acl->allow('User''Post', array('create''read'));

   // Give the Guests only create access for 'User'

   
$this->Acl->allow('Guest''User''create');

   }
}

?>


以看到,通过Acl,我们授予Admin所有在’User’和’Post’上的Aco。即,Admin可以对所有的user和post做“增读改删”四个
操作。或是这么说,任何控制器的行动,其中包括创建,读取,更新或删除一个’User’或’Post’的记录,Admin组
是都被允许的。如果某么用户属于Admin组,他也被授予了这样的权限。

‘User’这一Aro只允许对’Post’这一Aco进行Create以及Read操
作,这意味着一个’User’组可以访问到一个对一条’post‘记录可以进行’Create’和’Read’的操作的action,而这正是我们想要
的。我们想让任何用户属于’User’组能创造新的post,并且可以读取post记录。但是我们不希望所有的user(aro),能够’更新
update’或’删除delete’任何一条’Post'(Acos)。这意味着,如果你在’User’组中,你将不能访问’Post’的相关’U’和
‘D’的任何action。但创建这个Post的用户应该要有’u’和’d’的权限!!稍后我会为创建post记录的用户赋予这条post的全部权限,而
其它人对这条记录只有Read的权限。这样的做法,只为了明确你的概念。值得注意的是,以上我们没有对’User’这一aco做任何’allow’的设
定,所以这意味着默认为’User’的用户组的及’User’组下的成员,都没有获得对’User’记录的任何’CRUD'(acos)操作
。一个用户只有对自己的才能进行CRUD操作,对其他用户就没有权限。这就是我们为什么这么做的原因:)

‘Guest’这一aro只允许访问对’User’这一aco有创建的权限。也就是说,Guest只能创建一个新的用户账号,而不能对现有的账号做别的什么操作。

我们现在已基本设置完成了,我们希望在一个新用户加到这个系统中的时候,就得到相关的aro和aco信息。下面的代码就显示了如何手工创造aro和aco,以及如何设置权限。

Controller Class:

<?php 

class UsersController extends AppController

{

  var 
$name 'Users';

  var $components = array('Acl');

  function register()

  {

     if(!empty(
$this->data))

     {

        
$this->User->data $this->data;

        if ($this->User->validates())

        {

           if (
$this->User->save())

           {

               
$aro = $this->Acl->Aro;

               
$parent $aro->findByAlias('User');

               
$parentId $parent['aro']['id'];

               $aro->create();

               
$alias $this->User->name.'::'.$this->User->id;

               
$aro->save(

                 
'model'       => $this->User->name,

                 
'foreign_key' => $this->User->id,

                 
'parent_id'   => $parentId,

                 
'alias'   => $alias

                       
);

               $aco = $this->Acl->Aco;

               
$parent $aco->findByAlias('User');

               
$parentId $parent['aco']['id'];

               $aco->create();

               
$aco->save(

                 
'model'       => $this->User->name,

                 
'foreign_key' => $this->User->id,

                 
'parent_id'   => $parentId,

                 
'alias'       => $alias

                       
);

               $this->Acl->allow(

                    
$alias

                    
$alias

                    array(
'read','update'));

           }

        }

 

     }

  }

}

?>


上各位可以清楚看到,如何在新建用户的时候同时创建aro和aco信息。你也看到了如何让用户获得对自己操作的全部CRUD权限。或者这样说,用户A在网
站上注册了一个账号,同时他将获得一个与用户’5’。根据上述代码,系统会创建出一个别名为’User::5’的aro,同时在aros_acos表中创
建一条记录。这条记录说明’User::5’具有对’User::5’的aco的所有CRUD权限。现在除了用户A或是Admin组中的用户以外,其它人
都没有访问用户A账号的权限。现在我们来看下面的代码来证明我们刚刚的设想。

Controller Class:

<?php 

class TestController extends AppController

{

  var 
$name 'Test';

  var 
$components = array('Acl');

  var 
$uses = array('User');

  var 
$curLoggedInUserId 3;

  function view()

  { 

    
$aroAlias 'User::'.$curLoggedInUserId;

    
$acoAlias 'User::5';

    if ($this->Acl->check($aroAlias$acoAlias'read'))

    {

       echo 
'Read access allowed for User Id'.$curLoggedInUserId;

    }

    else

    {

       echo 
'Read access denied for User Id'.$curLoggedInUserId;

    }

  }

}

?>

当你访问以上页面(http://localhost/test/view)的时候,你会得到’access denied’的提示
。现在把$curloggedinuserid的值改为5,并再次访问这个页面,你会得到’allowed
access’的提示。这是因为这个时候来访者以用户A的身份登录。我们已经定义用户A拥有对用户A的账号有所有的权限。注注意当你设置$
curloggedinuserid = 1的时候,我们仍然得到了一个’allowed access’的提示
,为什么会造成这种情况呢?因为用户id为1的用户属于Admin组,他拥有对’User’这一aco的所有CRUD权限。上述代码是一个非常粗略的代
码,只是用于展示的目的,并不是说这就可以在你的实际应用中就这么编码。

以上是一本手工并且繁琐的方式,来创造aro和aco。现在,我现在会告诉你一个神奇的方式来创造aro和aco,而不需要花什么气力。所有要做的,只是利用cakephp1.2版中的Acl Behavior。以下是你将要放到Model ‘Post’中的代码。

Model Class:

<?php 

class Post extends AppModel{

var 
$name 'Post';

var 
$actsAs = array('Acl'=>'controlled');

// 'controlled' means you want to create a 'aco'

// 'requester' means you want to create an 'aro'

// 译注:'controlled'及'requester'可以指定Acl组件现在是以aco或是aro方式来工作

/**

 * Returns the parent Alias for current

 */

function parentNode()

{

    return 
$this->name;

}

}

?>

上述代码,将会在创建一个新post的时候自动地创建一个aco。而Acl Behavior来做所有的其它事情。在Acl Behavior中,有一个’afterSave’的回调方法。这个方法将在这个model每次save动作之后自动地调用。

Acl behavior甚至可以在post被删除的时候自动地删除关联的aco,而不需要多做些什么。很酷吧?hiahia!现在如果你想对新创建出的aco设置一些权限的话应该怎么做呢?请看下面的代码:

Controller Class:

<?php 

class PostsController extends AppController {

   var $name 'Posts';

   var 
$helpers = array('Html''Form' );

   var 
$uses = array('Post');

   var 
$components = array('Acl');

   function add() {

       if(!empty(
$this->data)) {

       
$this->Post->data $this->data;

            

           if (
$this->Post->validates())

       {

         
$this->Post->create();

                

        if(
$this->Post->save($this->data)) 

                { 

                    
$acoNode = array('model'=>$this->Post->name,

                                     
'foreign_key' =>$this->Post->id);

                    $aroNode = array('model'=>'User',

                                   
'foreign_key'=>$this->getUserId());

            // User has full control of the post he created

            
$this->Acl->allow($aroNode$acoNode'*');

        }

    }

    }

}

?>

因此,如果从Posts这一controller的add方法保存数据成功,我们知道Aco已经创建出来了,然后我们要做的就是为适当的aro和aco节点设计相关的CRUD权限,一切就这样完成了!

我很欢迎所有的评论和建议。如果你在操作过程中出现了什么问题,请联系我。baking还是个很有趣的活的。

Cheers,
Ketan Patel

Copyright © 2007. All Rights Reserved.

发表评论

电子邮件地址不会被公开。 必填项已用*标注