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;
});

這樣每次從一個方法跳轉到另外一個方法以前程序都會先去查詢一下權限控制列表,看看用戶對即將跳轉的方法是否有訪問權限,若沒有權限則跳轉到插件中指定的方法。session

 

此外,還能夠使用繼承機制來構造更復雜的角色,只須要在添加角色的函數的第二個參數中寫上要繼承的那個角色的實例便可:app

// 建立角色函數

$roleAdmins = new Role("Administrators", "Super-User role");post

$roleGuests = new Role("Guests");性能

// 添加 "Guests" 到 ACLthis

$acl->addRole($roleGuests);spa

 

// 使Administrators繼承Guests的訪問權限插件

$acl->addRole($roleAdmins, $roleGuests);code

 

爲了提升性能, Phalcon\Acl 的實例能夠被實例化到APC, session, 文本或數據庫中:

 // 保存實例化的數據到文本文件中

 file_put_contents("app/security/acl.data", serialize($acl));

 // 返序列化

$acl = unserialize(file_get_contents("app/security/acl.data"));

相關文章
相關標籤/搜索