CakePHP ACL Veritabanı Kurulumu: ARO / ACO yapısı?

1 Cevap php

Ben CakePHP'de ACL uygulamak için mücadele ediyorum. Vb cake manual yanı sıra çok sayıda diğer öğreticiler, Blog yazılarına belgeleri okuduktan sonra, ben boşluklar birçok doldurunuz yardımcı oldu Aran Johnson'ın mükemmel öğretici buldum. Özellikle o kullandığı ARO ağaç yapısında - Onun örnekleri Ben birkaç yerde olsa gördüm başkaları ile çatışma gibi görünüyor.

Onun içinde examples Onun kullanıcı grupları en genel kullanıcı türü ağacın tepesinde olmak ve çocukların her biri daha kısıtlı erişim türü için kapalı dallanma ile, bir basamaklı ağaç olarak ayarlanmıştır. Başka bir yerde, genellikle aynı genel kullanıcı türü bir çocuk olarak, her kullanıcı türü gördüm.

Eğer Aros ve CakePKP'deki ACOS nasıl kurarım? Herhangi ve tüm ipuçları takdir!

1 Cevap

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;
}