簡體   English   中英

CakePHP ACL數據庫設置:ARO / ACO結構?

[英]CakePHP ACL Database Setup: ARO / ACO structure?

我正在努力在CakePHP中實現ACL。 在閱讀了蛋糕手冊中的文檔以及其他一些教程,博客文章等之后,我發現了Aran Johnson的優秀教程,這有助於填補許多空白。 他的例子似乎與我在一些地方見過的其他人發生沖突 - 特別是在他使用的ARO樹結構中。

在他的示例中,他的用戶組被設置為級聯樹,最常用的用戶類型位於樹的頂部,並且其子節點為每個更受限制的訪問類型分支。 在其他地方,我經常看到每個用戶類型都是相同通用用戶類型的子類。

你如何在CakePHP中設置你的ARO和ACO? 任何和所有提示贊賞!

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()方法在AppControllerbeforeFilter( )回調中調用。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM