本文未对原文逐字翻译,只是将其方法做了简要的说明。详情见原文(Zend Framework 2 Acl using a module and plugin)。
本文将使用一个模块和插件来介绍Zend Framework 2 Acl的用法。
首先我们参照手册中的“Application”和“Album”模块建立一个名字为“MyAcl”的模块。
setp 1: 在“MyAcl”模块中建立一个名为“Module.php”的文件。
Module.php:
<?php namespace MyAcl; use Zend\ModuleManager\ModuleManager; use Zend\Mvc\MvcEvent, Zend\ModuleManager\Feature\AutoloaderProviderInterface, Zend\ModuleManager\Feature\ConfigProviderInterface; //class Module class Module { public function getConfig() { return include __DIR__ . '/config/module.config.php'; } // 添加Acl public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager(); $eventManager->attach('route', array($this, 'loadConfiguration'), 2); // 你可以按照需要添加其他函数 } public function loadConfiguration(MvcEvent $e) { $application = $e->getApplication(); $sm = $application->getServiceManager(); $sharedManager = $application->getEventManager()->getSharedManager(); $router = $sm->get('router'); $request = $sm->get('request'); $matchedRoute = $router->match($request); if (null !== $matchedRoute) { $sharedManager->attach('Zend\Mvc\Controller\AbstractActionController','dispatch', function($e) use ($sm) { $sm->get('ControllerPluginManager')->get('MyAclPlugin') ->doAuthorization($e); //pass to the plugin... },2 ); } } /* * 添加当前模块的初始化函数 * 详见:http://blog.evan.pro/module-specific-layouts-in-zend-framework-2 */ public function init(ModuleManager $moduleManager) { $sharedEvents = $moduleManager->getEventManager()->getSharedManager(); $sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) { // This event will only be fired when an ActionController under the MyModule namespace is dispatched. $controller = $e->getTarget(); //$controller->layout('layout/zfcommons'); // points to module/Album/view/layout/album.phtml }, 100); } public function getAutoloaderConfig() { return array( 'Zend\Loader\ClassMapAutoloader' => array( __DIR__ . '/autoload_classmap.php', ), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ), ); } }
Step 2: 配置module.config.php
(path: “module/MyAcl/config”)
<?php return array( 'controller_plugins' => array( 'invokables' => array( 'MyAclPlugin' => 'MyAcl\Controller\Plugin\MyAclPlugin', ) ), );
Step 3: 配置MyAclPlugin.php
(path: “module/MyAcl/src/MyAcl/Controller/Plugin”)
<?php namespace MyAcl\Controller\Plugin; use Zend\Mvc\Controller\Plugin\AbstractPlugin, Zend\Session\Container as SessionContainer, Zend\Permissions\Acl\Acl, Zend\Permissions\Acl\Role\GenericRole as Role, Zend\Permissions\Acl\Resource\GenericResource as Resource; class MyAclPlugin extends AbstractPlugin { protected $sesscontainer; private function getSessContainer() { if (!$this->sesscontainer) { $this->sesscontainer = new SessionContainer('zftutorial'); } return $this->sesscontainer; } public function doAuthorization($e) { // 设置 ACL $acl = new Acl(); $acl->deny(); // 设置默认状态为禁止访问 //$acl->allow(); // 或者设置默认为访问状态 # 添加角色,角色之间可以继承,例如“user”拥有“anonymous”的所有权限。 $acl->addRole(new Role('anonymous')); $acl->addRole(new Role('user'), 'anonymous'); $acl->addRole(new Role('admin'), 'user'); # 添加资源 $acl->addResource('application'); // Application 模块 $acl->addResource('album'); // Album 模块 ################ 设置权限 ####################### // $acl->allow('角色', '资源', '控制器:方法'); // Application --------------------------> $acl->allow('anonymous', 'application', 'index:index'); $acl->allow('anonymous', 'application', 'profile:index'); // Album --------------------------------> $acl->allow('anonymous', 'album', 'album:index'); $acl->allow('anonymous', 'album', 'album:add'); $acl->deny('anonymous', 'album', 'album:hello'); $acl->allow('anonymous', 'album', 'album:view'); $acl->allow('anonymous', 'album', 'album:edit'); // 同样允许路由为 “zf2-tutorial.com/album/edit/1” 的访问 //$acl->deny('anonymous', 'Album', 'Album:song'); $controller = $e->getTarget(); $controllerClass = get_class($controller); $moduleName = strtolower(substr($controllerClass, 0, strpos($controllerClass, '\\'))); $role = (! $this->getSessContainer()->role ) ? 'anonymous' : $this->getSessContainer()->role; $routeMatch = $e->getRouteMatch(); $actionName = strtolower($routeMatch->getParam('action', 'not-found')); // 获取方法名 $controllerName = $routeMatch->getParam('controller', 'not-found'); // 获取控制器名 $controllerName = strtolower(array_pop(explode('\\', $controllerName))); /* print '<br>$moduleName: '.$moduleName.'<br>'; print '<br>$controllerClass: '.$controllerClass.'<br>'; print '$controllerName: '.$controllerName.'<br>'; print '$action: '.$actionName.'<br>'; */ #################### 检查权限 ######################## if ( ! $acl->isAllowed($role, $moduleName, $controllerName.':'.$actionName)){ $router = $e->getRouter(); // $url = $router->assemble(array(), array('name' => 'Login/auth')); // assemble a login route $url = $router->assemble(array(), array('name' => 'application')); $response = $e->getResponse(); $response->setStatusCode(302); // redirect to login page or other page. $response->getHeaders()->addHeaderLine('Location', $url); $e->stopPropagation(); } } }
在上面的示例中,我们对anonymous用户设置了两个禁止访问的路由:”zf2-tutorial.com/album/hello”和”zf2-tutorial.com/album/song”。当其访问这两个路由时将会被重定向到”zf2-tutorial.com/application”。
Step 4: 在application.config.php中添加当前模块
<?php return array( 'modules' => array( 'Application', 'Album', 'MyAcl', ), ....(其他参数未显示) ); 转自http://mushroot.com/zf2-zend-framework-2-rumen-acl-fangwenkongzhiliebiao