原文出处:How to use ACL with Cake PHP 1.2.x?
在开始之前,我想你应该有一些ACL的基本概念以及它应该用在什么地方。如果你对这些不甚了解的话,请阅读http://manual.cakephp.org/chapter/acl
首先你应该通过在命令行下输入这行命令来创建ACL所需要的数据库
cake acl initdb现在,我们将初始化一些更高级别的aro和aco设置。你也可以通过控制台命令来运行。不过,我更喜欢通过controller来运行,并没有什么特别,照着做就好了!
Aros (可以是用户或是某项服务等)是一个要求访问Acos(可以是controller,action或其它服务)的东西。但在这个例子里,我们将限制Aros作为users,而把Acos作为controllers。我们将设置以下Aros(用户) :
- Admin
- |-->User::1
- User
- Guest
我们还将创建以下的Acos,也就是controllers
- User
- 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组,他也被授予了这样的权限。
'Guest'这一aro只允许访问对'User'这一aco有创建的权限。也就是说,Guest只能创建一个新的用户账号,而不能对现有的账号做别的什么操作。
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'));
}
}
}
}
}
?>
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, '*');
}
}
}
}
?>
我很欢迎所有的评论和建议。如果你在操作过程中出现了什么问题,请联系我。baking还是个很有趣的活的。
Cheers,
Ketan Patel

