PHP框架Phalcon 之 ACL

phalcon_acl.jpg

使用以下圖解釋這個組件:git

phalcon_acl_adapter_database.jpg

實際最終真正要使用的是access_list(ACL),可是這個ACL的填充的場景通常是在後臺,先添加具體的role,而後添加resource以及resource_list(通常resource以及resource_list是固定的,由於這兩個東西通常對應控制器和控制器的動做),再而後針對role設置access_list,每條access_list組成有roles_name、resources_name、access_name、allowed,檢查某個用戶(屬於某個role)是否能夠執行某控制器和動做,就檢查對應的控制器和動做在列表中它的allowed的值。若是access_list已經設置好了,在檢查用戶權限這個步驟,徹底能夠只使用access_list。PhalconAclAdapter抽象類要求全部的適配器都要提供添加角色,添加資源,添加訪問列表,判斷權限等功能。github

對於角色繼承,好比有角色A和B,B繼承A,若是要獲取A的ACL,只要去access_list查詢roles_name爲A的記錄便可,若是是B,則要查詢roles_name爲A和B的記錄。數據庫

從邏輯上看,role,roles_inherits, resource, resource_access應不是ACL對象的組成部分,可是因爲要管理這些資源,全部提供了對應方法。緩存

//acl object
$acl = new \Phalcon\Acl\Adapter\Memory();
$acl->setDefaultAction(\Phalcon\Acl::DENY);
 
//role name description
$roleAdmins = new \Phalcon\Acl\Role("Admin","Super-User role");        
$roleGuests = new \Phalcon\Acl\Role("Guests");
$acl->addRole($roleGuests);
 
//roles_inhelit roles_name roles_inherit
$acl->addRole($roleAdmins, $roleGuests);
 
//resource name description
//resource_accesses resources_name access_name
$customersResource = new \Phalcon\Acl\Resource("Customers");
$acl->addResource($customersResource,array("search","edit"));
 
//access_list roles_name resources_name access_name
$acl->allow("Admin","Customers","search");
 
//check acl
//echo $acl->isAllowed("Admin","Customers","edit");
echo $acl->isAllowed("Admin","Customers","update");

通常至少要在執行路由前要判斷用戶是否具備權限(通常在beforeDispatch中),因此ACL應該在它以前得到填充。如下代碼可參考:session

public function beforeDispatch(Event $event, Dispatcher $dispatcher) {
 
    $auth = $this->session->get('auth');
    if (!$auth){
        $role = 'Guests';
    } else {
        $role = 'Users';
    }
 
    $controller = $dispatcher->getControllerName();
    $action = $dispatcher->getActionName();
 
    $acl = $this->getAcl();
 
    $allowed = $acl->isAllowed($role, $controller, $action);
    if ($allowed != Acl::ALLOW) {
        $this->flash->error("You don't have access to this module");
        $dispatcher->forward(
            array(
                'controller' => 'index',
                'action' => 'index'
            )
        );
        return false;
    }
}

這裏的getAcl()方法就是重點。參考:this

public function getAcl() {
    if (!isset($this->persistent->acl)) {
  
        $acl = new Phalcon\Acl\Adapter\Memory();
 
        $acl->setDefaultAction(Phalcon\Acl::DENY);
 
        //Register roles
        $roles = array(
            'users'  => new Phalcon\Acl\Role('Users'),
            'guests' => new Phalcon\Acl\Role('Guests')
        );
        foreach ($roles as $role) {
             $acl->addRole($role);
        }
 
        //Private area resources
        $privateResources = array(
            'companies'    => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
            'products'     => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
            'producttypes' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
            'invoices'     => array('index', 'profile')
    );
        foreach ($privateResources as $resource => $actions) {
            $acl->addResource(new Phalcon\Acl\Resource($resource), $actions);
        }
 
        //Public area resources
        $publicResources = array(
            'index'   => array('index'),
            'about'   => array('index'),
            'session' => array('index', 'register', 'start', 'end'),
            'contact' => array('index', 'send')
        );
        foreach ($publicResources as $resource => $actions) {
            $acl->addResource(new Phalcon\Acl\Resource($resource), $actions);
        }
 
        //Grant access to public areas to both users and guests
        foreach ($roles as $role) {
            foreach ($publicResources as $resource => $actions) {
                $acl->allow($role->getName(), $resource, '*');
            }
        }
 
        //Grant acess to private area to role Users
        foreach ($privateResources as $resource => $actions) {
            foreach ($actions as $action){
                $acl->allow('Users', $resource, $action);
            }
        }
 
        //The acl is stored in session, APC would be useful here too
        $this->persistent->acl = $acl;
    }
 
    return $this->persistent->acl;
}

這裏把acl對象保存在persistent中。spa

alc_process.jpg

全部角色 資源 訪問列表這些應該是要可配置而且是要保存起來的。可是Phalcon當前只提供PhalconAclAdapterMemory適配器,在它實例化後你須要手動填充它,資源訪問列表能夠來自數據庫等,而後能夠把這個對象緩存起來,https://github.com/phalcon/in...中提供了一個保存到數據庫的適配器,它能夠根據數據表自動填充,能夠調用相關方法添加資源、角色、訪問列表,而這些若是使用PhalconAclAdapterMemory,那麼就要本身去實現。code

相關文章
相關標籤/搜索