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