CakePHP'nin yerleşik ACL sistemi gerçekten güçlü, ama kötü fiili uygulama detayları açısından belgelenmiştir. Aşağıdaki gibi CakePHP tabanlı projeler bir dizi bazı başarı ile kullanmış olduğunuz bir sistemdir.
Bu olmuş bazı grup-düzeyinde erişim sistemlerinin bir değişiklik var documented elsewhere. Bizim sistemin amacı, kullanıcıların bir grup düzeyinde yetkili olan basit bir sistem var, ama onlar tarafından oluşturulan öğeleri belirli ek haklara sahip, ya da kullanıcı başına bazında olabilir. Biz aros_acos
tablodaki (her ARO için ya da daha spesifik,) belirli her kullanıcı için giriş oluşturmak zorunda önlemek istedim.
Biz bir Kullanıcılar tablo var, ve bir Roller tablo.
Users
user_id, user_name, role_id
Roles
id, role_name
Her rol için ARO ağacı (genellikle 4 rolleri var - Yetkisiz Konuk (id 1) Yetkili Kullanıcı (id 2) Site Yöneticisi (id 3) ve Yönetici (id 4)) oluşturun:
cake acl create aro / Role.1
cake acl create aro 1 Role.2 ... etc ...
Bundan sonra, kek komut satırı aracı bunu yapmaz gibi, SQL veya phpMyAdmin veya tüm bunlar için takma ad eklemek için benzer kullanmak zorunda. Biz bizim tüm 'Rol {id}' kullanın ve 'kullanıcı {id}'.
Biz o zaman bir KÖK ACO oluşturmak -
cake acl create aco / 'ROOT'
ve sonra bu KÖK bir altındaki tüm kontrolörler için ACOS oluşturun:
cake acl create aco 'ROOT' 'MyController' ... etc ...
Şimdiye kadar o kadar normal. Biz ACL bileşenin actionMap ek bir eylem olarak kullanabilirsiniz _editown
denilen aros_acos tablodaki ek bir alan eklemek.
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;
Daha sonra kurulum Auth bileşeni AclComponent :: çek karşı istenen denetleyicisi / eylem (doğrular 'rezil' yöntemi,) kullanmak olabilir. App_controller biz çizgisinde bir şey var:
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 ...
}
}
Yine, bu oldukça standart CakePHP şeyler. Biz o zaman erişim için bir grup ARO veya bir kullanıcıyı ARO denetlemek için olmadığını kontrol grubu düzey şeyler ekler AppController bir CheckAccess yöntemi vardır:
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()
ve checkAccess()
yöntemleri AppController
's beforeFilter(
) geri arama denir. Sadece istenen öğenin User_id anda doğrulanmış kullanıcı olarak aynı olduğunu kontrol eder çok AppControler bir isMine
yöntemi (aşağıya bakınız) var. Ben netlik için bu dışarı bıraktım.
Hepsi bu kadar var gerçekten. Daha sonra izin verebilirsiniz / inkar belli gruplar, belli acos erişim -
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'
Ben resmi olsun eminim.
Her neyse, bu Cevabým yol uzun ben olmak amacıyla daha, ve muhtemelen hiçbir anlamda yanındaki yapar, ama ben size biraz yardım umuyoruz ...
- Düzenle -
İstendiği gibi, burada bir (tamamen netlik için - bir sürü şey burada anlamsız bizim Demirbaş kodu var) düzenlenmiş bizim AppController var isMine()
yöntemi. Ben çok şeyler hata kontrolü bir çok kaldırdık, ama bu onun özüdür:
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;
}