[英]CakePHP ACL Database Setup: ARO / ACO structure?
CakePHP的內置ACL系統非常強大,但在實際實現細節方面記錄不佳。 我們在許多基於CakePHP的項目中使用的系統如下所示。
它是對其他地方記錄的一些組級訪問系統的修改。 我們的系統的目標是建立一個簡單的系統,用戶在組級別上獲得授權,但他們可以對由他們創建的項目或每個用戶具有特定的附加權限。 我們希望避免在aros_acos
表中為每個用戶(或者更具體地說,對每個ARO)創建特定條目。
我們有一個Users表和一個Roles表。
用戶
user_id, user_name, role_id
角色
id, role_name
為每個角色創建ARO樹(我們通常有4個角色 - 未授權訪客(id 1),授權用戶(id 2),站點主持人(id 3)和Administrator(id 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()
和checkAccess()
方法在AppController
的beforeFilter(
)回調中調用。 AppControler中也有一個isMine
方法(見下文), isMine
檢查所請求項的user_id是否與當前經過身份驗證的用戶相同。 為了清楚起見,我把它留了下來。
這就是它的全部內容。 然后,您可以允許/拒絕特定組訪問特定的acos -
cake acl grant 'Role-2' 'MyController' 'read'
cake acl grant 'Role-2' 'MyController' 'editown'
cake acl deny 'Role-2' 'MyController' 'update'
cake acl deny 'Role-2' 'MyController' 'delete'
我相信你能得到這張照片。
無論如何,這個答案的方式比我預想的要長,而且可能接下來沒什么意義,但我希望這對你有所幫助......
- 編輯 -
根據要求,這里是一個編輯過的(純粹為了清晰 - 我們的樣板代碼中有很多東西在這里沒有意義) isMine()
方法,我們在AppController中。 我也刪除了很多錯誤檢查的東西,但這是它的本質:
function isMine($model=null, $id=null, $usermodel='User', $foreignkey='user_id') {
if(empty($model)) {
// default model is first item in $this->uses array
$model = $this->uses[0];
}
if(empty($id)) {
if(!empty($this->passedArgs['id'])) {
$id = $this->passedArgs['id'];
} elseif(!empty($this->passedArgs[0])) {
$id = $this->passedArgs[0];
}
}
if(is_array($id)) {
foreach($id as $i) {
if(!$this->_isMine($model, $i, $usermodel, $foreignkey)) {
return false;
}
}
return true;
}
return $this->_isMine($model, $id, $usermodel, $foreignkey);
}
function _isMine($model, $id, $usermodel='User', $foreignkey='user_id') {
$user = Configure::read('curr.loggedinuser'); // this is set in the UsersController on successful login
if(isset($this->$model)) {
$model = $this->$model;
} else {
$model = ClassRegistry::init($model);
}
//read model
if(!($record = $model->read(null, $id))) {
return false;
}
//get foreign key
if($usermodel == $model->alias) {
if($record[$model->alias][$model->primaryKey] == $user['User']['id']) {
return true;
}
} elseif($record[$model->alias][$foreignkey] == $user['User']['id']) {
return true;
}
return false;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.