phalcon——访问控制列表ACL
一个完整的使用实例(将acl封装成一个插件使用):
use Phalcon\Acl; use Phalcon\Acl\Role; use Phalcon\Acl\Resource; use Phalcon\Events\Event; use Phalcon\Mvc\User\Plugin; use Phalcon\Mvc\Dispatcher; use Phalcon\Acl\Adapter\Memory as AclList; class SecurityPlugin extends Plugin { //返回一个已存在的或新创建的acl列表 public function getAcl() { if(!isset($this->persistent->acl)) { $acl = new AclList(); //设置默认访问级别为“拒绝” $acl->setDefaultAction(Acl::DENY); //添加角色 $roles = array( 'users' => new Role('Users'), 'guests' => new Role('Guests') ); foreach($roles as $role) { $acl->addRole($role); } //添加私有资源 $privateResources = array( 'posts' => array('post'), 'comments' => array('comment') ); foreach($privateResources as $resource => $actions) { $acl->addResource(new Resource($resource),$actions); } //添加公有资源 $publicResources = array( 'index' => array('index'), 'register' => array('index'), 'login' => array('index','start','end'), 'posts' => array('index','detail') ); foreach($publicResources as $resource => $actions) { $acl->addResource(new Resource($resource),$actions); } //公有资源访问控制 foreach($roles as $role) { foreach($publicResources as $resource => $actions) { foreach($actions as $action) { $acl->allow($role->getName(),$resource,$action); } } } //私有资源访问控制 foreach($privateResources as $resource => $actions) { foreach($actions as $action) { $acl->allow('Users',$resource,$action); } } $this->persistent->acl = $acl; } return $this->persistent->acl; } //查询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) { //需要用户登录才有权限 $dispatcher->forward(array( 'controller' => 'login', 'action' => 'index' )); $this->session->destroy(); return false; } } } 在注入调度控制器时绑定到一个事件控制器中: $di->set('dispatcher',function() use ($di) { $eventsManager = new EventsManager; $eventsManager->attach('dispatch:beforeDispatch',new SecurityPlugin); $dispatcher = new Dispatcher; $dispatcher->setEventsManager($eventsManager); return $dispatcher; });
这样每次从一个方法跳转到另一个方法之前程序都会先去查询一下权限控制列表,看看用户对即将跳转的方法是否有访问权限,若没有权限则跳转到插件中指定的方法。
此外,还可以使用继承机制来构造更复杂的角色,只需要在添加角色的函数的第二个参数中写上要继承的那个角色的实例即可:
// 创建角色
$roleAdmins = new Role("Administrators", "Super-User role");
$roleGuests = new Role("Guests");
// 添加 "Guests" 到 ACL
$acl->addRole($roleGuests);
// 使Administrators继承Guests的访问权限
$acl->addRole($roleAdmins, $roleGuests);
为了提高性能, Phalcon\Acl 的实例可以被实例化到APC, session, 文本或数据库中:
// 保存实例化的数据到文本文件中
file_put_contents("app/security/acl.data", serialize($acl));
// 返序列化
$acl = unserialize(file_get_contents("app/security/acl.data"));