使用如下图解释这个组件:
实际最终真正要使用的是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抽象类要求所有的适配器都要提供添加角色,添加资源,添加访问列表,判断权限等功能。
对于角色继承,比如有角色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应该在它之前获得填充。以下代码可参考:
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()方法就是重点。参考:
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中。
所有角色 资源 访问列表这些应该是要可配置并且是要保存起来的。但是Phalcon当前只提供PhalconAclAdapterMemory适配器,在它实例化后你需要手动填充它,资源访问列表可以来自数据库等,然后可以把这个对象缓存起来,https://github.com/phalcon/in...中提供了一个保存到数据库的适配器,它可以根据数据表自动填充,可以调用相关方法添加资源、角色、访问列表,而这些如果使用PhalconAclAdapterMemory,那么就要自己去实现。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。