我正在努力在CakePHP中实现ACL。在阅读了cake manual以及其他几个教程,博客文章等文档之后,我发现了Aran Johnson的优秀教程,它帮助填补了许多空白。他的例子似乎与我在一些地方见过的其他人发生冲突 - 特别是在他使用的ARO树结构中。
在他的examples中,他的用户组被设置为级联树,最常用的用户类型位于树的顶部,并且其子节点为每个更受限制的访问类型分支。在其他地方,我经常看到每个用户类型都是相同通用用户类型的子级。
如何在CakePHP中设置ARO和ACO?任何和所有提示赞赏!
答案 0 :(得分:49)
CakePHP的内置ACL系统非常强大,但在实际实现细节方面记录不足。我们在许多基于CakePHP的项目中取得了一些成功的系统如下。
这是对documented elsewhere的某些组级访问系统的修改。我们的系统的目标是建立一个简单的系统,用户在组级别上获得授权,但他们可以对由他们创建的项目或每个用户具有特定的附加权限。我们希望避免在aros_acos
表中为每个用户(或者更具体地说,对每个ARO)创建特定条目。
我们有一个Users表和一个Roles表。
用户强>
user_id, user_name, role_id
<强>角色强>
id, role_name
为每个角色创建ARO树(我们通常有4个角色 - 未授权访客(身份1),授权用户(身份2),网站主持人(身份3)和管理员(身份4)):
cake acl create aro / Role.1
cake acl create aro 1 Role.2 ... etc ...
在此之后,您必须使用SQL或phpMyAdmin或类似的方法为所有这些添加别名,因为cake命令行工具不会这样做。我们所有人都使用'Role- {id}'和'User- {id}'。
然后我们创建一个ROOT ACO -
cake acl create aco / 'ROOT'
然后为此ROOT下的所有控制器创建ACO:
cake acl create aco 'ROOT' 'MyController' ... etc ...
到目前为止很正常。我们在aros_acos表中添加了一个名为_editown
的附加字段,我们可以将其用作ACL组件的actionMap中的附加操作。
CREATE TABLE IF NOT EXISTS `aros_acos` (
`id` int(11) NOT NULL auto_increment,
`aro_id` int(11) default NULL,
`aco_id` int(11) default NULL,
`_create` int(11) NOT NULL default '0',
`_read` int(11) NOT NULL default '0',
`_update` int(11) NOT NULL default '0',
`_delete` int(11) NOT NULL default '0',
`_editown` int(11) NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `acl` (`aro_id`,`aco_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然后我们可以设置Auth组件以使用'crud'方法,该方法根据AclComponent :: check()验证所请求的控制器/操作。在app_controller中,我们有以下几点:
private function setupAuth() {
if(isset($this->Auth)) {
....
$this->Auth->authorize = 'crud';
$this->Auth->actionMap = array( 'index' => 'read',
'add' => 'create',
'edit' => 'update'
'editMine' => 'editown',
'view' => 'read'
... etc ...
);
... etc ...
}
}
同样,这是相当标准的CakePHP。然后我们在AppController中有一个checkAccess方法,它添加了组级别的东西来检查是否要检查组ARO或用户ARO是否有访问权限:
private function checkAccess() {
if(!$user = $this->Auth->user()) {
$role_alias = 'Role-1';
$user_alias = null;
} else {
$role_alias = 'Role-' . $user['User']['role_id'];
$user_alias = 'User-' . $user['User']['id'];
}
// do we have an aro for this user?
if($user_alias && ($user_aro = $this->User->Aro->findByAlias($user_alias))) {
$aro_alias = $user_alias;
} else {
$aro_alias = $role_alias;
}
if ('editown' == $this->Auth->actionMap[$this->action]) {
if($this->Acl->check($aro_alias, $this->name, 'editown') and $this->isMine()) {
$this->Auth->allow();
} else {
$this->Auth->authorize = 'controller';
$this->Auth->deny('*');
}
} else {
// check this user-level aro for access
if($this->Acl->check($aro_alias, $this->name, $this->Auth->actionMap[$this->action])) {
$this->Auth->allow();
} else {
$this->Auth->authorize = 'controller';
$this->Auth->deny('*');
}
}
}
在setupAuth()
的{{1}})回调中调用checkAccess()
和AppController
方法。 AppControler中也有一个beforeFilter(
方法(见下文),只检查所请求项目的user_id是否与当前经过身份验证的用户相同。为了清楚起见,我把它留了下来。
这就是它的全部内容。然后,您可以允许/拒绝特定组访问特定的acos -
isMine
cake acl grant 'Role-2' 'MyController' 'read'
cake acl grant 'Role-2' 'MyController' 'editown'
cake acl deny 'Role-2' 'MyController' 'update'
我相信你能得到这张照片。
无论如何,这个答案的方式比我预想的要长,而且可能接下来没什么意义,但我希望这对你有所帮助......
- 编辑 -
根据要求,这里是一个经过编辑的(纯粹为了清晰起见 - 我们的样板代码中有很多东西在这里没有意义)我们在AppController中有cake acl deny 'Role-2' 'MyController' 'delete'
方法。我也删除了很多错误检查的东西,但这是它的本质:
isMine()