jkardynia / acl-annot
Zend Framework 2 的 ACL 注解
Requires
- php: >=5.3.3
- doctrine/common: 2.3.0
- zendframework/zend-mvc: 2.2.*
- zendframework/zend-permissions-acl: 2.2.*
This package is not auto-updated.
Last update: 2024-09-24 06:21:32 UTC
README
使用 Zend Framework 2 的 ACL 注解,此包允许您通过注解在 Zend 控制器中编写 ACL 规则。
安装
您可以通过 composer 安装它。只需将以下内容添加到 composer.json 中的依赖项
"jkardynia/acl-annot": "*"
使用方法
使用 ACL 注解非常简单。您需要做的就是使用 @Acl 注解来定义您在定义控制器的地方的用户角色的访问规则。
在控制器中添加规则
以下示例将向您展示如何使用 ACL 注解与 AlbumController(来自 Zend Framework 2 教程的示例)一起使用 - 入门 - 创建控制器
<?php namespace Album\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; use \jkardynia\Annotations\Permissions\Acl\Acl; class AlbumController extends AbstractActionController { /** * @Acl("Allow", roles="admin, guest") */ public function indexAction() { } /** * @Acl("Allow", roles="admin") */ public function addAction() { } /** * @Acl("Allow", roles="admin") */ public function editAction() { } /** * @Acl("Allow", roles="admin") */ public function deleteAction() { } }
更改不多。我仅通过 use 关键字导入了 ACL 注解类,并使用了这些注解。如您所见,我只允许访客访问 indexAction,并允许管理员访问所有操作。
这是定义 ACL 规则,但在这些规则开始工作之前,您的模块必须收集所有规则。
构建访问控制列表
ACL 应在应用初始化之初就填充。考虑到这一点,您应该通过将新的闭包附加到 MvcEvent 来准备您的模块。您可以这样操作
<?php namespace Album; use Zend\Mvc\MvcEvent; use \jkardynia\Zend\Permissions\Acl\AclItemsCollector; use Zend\ModuleManager\Feature\AutoloaderProviderInterface; use Zend\ModuleManager\Feature\ConfigProviderInterface; class Module implements AutoloaderProviderInterface, ConfigProviderInterface { /** * @var \Zend\Permissions\Acl\Acl */ private $acl = null; public function init(\Zend\ModuleManager\ModuleManager $m){ $event = $m->getEventManager()->getSharedManager(); $event->attach('Zend\Mvc\Application', MvcEvent::EVENT_BOOTSTRAP, function (MvcEvent $e){ $collector = new AclItemsCollector(); $collector->getAcl()->addRole('guest'); $collector->getAcl()->addRole('admin', 'guest'); $collector->addEntriesFromResourceClass('Album\Controller\AlbumController'); $this->acl = $collector->getAcl(); }); } // other stuff }
现在我们有了一个访问控制列表,我们可以使用它来检查当前用户的访问权限。注意,我添加了一个私有字段 \Zend\Permissions\Acl\Acl $acl,它是在 ACL 初始化回调中初始化的。我们稍后会用到它。
检查访问
检查用户是否有权访问我们的控制器是 ACL 系统的主要目的。我们应该在 ActionController dispatch 中检查访问权限。为此,首先我们必须在模块中添加一个新的事件订阅者(回调)。
class Module implements AutoloaderProviderInterface, ConfigProviderInterface { //some initialization public function onBootstrap(MvcEvent $e){ $eventManager = $e->getApplication()->getEventManager(); $eventManager->attach(MvcEvent::EVENT_ROUTE, function(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) { $acl = $this->acl; $sharedManager->attach('Zend\Mvc\Controller\AbstractActionController', MvcEvent::EVENT_DISPATCH, function($event) use ($sm, $acl) { $userRole = new \Zend\Permissions\Acl\Role\GenericRole('guest'); try{ $sm->get('ControllerPluginManager')->get('Acl', $acl)->checkAccess($event, $userRole); }catch(AccessDeniedException $e){ $event->getTarget()->plugin('redirect')->toUrl('access-denied'); return false; } }); } }); } //other stuff }
那里发生了什么?我们只是在适当的回调中附加了回调。最重要的事情是
$userRole = new \Zend\Permissions\Acl\Role\GenericRole('guest'); // you can get it from session try{ $sm->get('ControllerPluginManager')->get('Acl', $acl)->checkAccess($event, $userRole); }catch(AccessDeniedException $e){ $event->getTarget()->plugin('redirect')->toUrl('access-denied'); return false; }
在那里,我们从 ControllerPluginManager 获取 Acl 插件,并使用它来检查访问权限。如果访问被拒绝,将会抛出异常,所以我捕获它并将重定向到访问被拒绝的信息页面。
还有最后一件事要做。我们必须注册 Acl 插件。
注册 ACL 插件
为了在您的模块中注册任何新的插件,您只需在 module.config.php 文件中添加一行即可
'controller_plugins' => array( 'invokables' => array( 'Acl' => '\jkardynia\Zend\Controller\Plugin\Acl', ) )
现在一切就绪 - 您可以使用注解来提供和检查对您控制器的访问 :)
性能
说实话,注解很慢,如果您想在真实应用中使用它们,您应该启用缓存。幸运的是,这个项目使用了 Doctrine Annotations 提供的很好的缓存系统。您可以使用提供的缓存策略之一,例如:APC、Memcache、Files 等。您可以直接从您的模块中配置缓存。您需要做的就是使用支持缓存的 Reader 初始化 AclItemsCollector。以下是一个文件系统缓存的示例
<?php namespace Album; use Zend\Mvc\MvcEvent; use \jkardynia\Zend\Permissions\Acl\AclItemsCollector; use Zend\ModuleManager\Feature\AutoloaderProviderInterface; use Zend\ModuleManager\Feature\ConfigProviderInterface; use \Zend\Permissions\Acl\Acl; use \jkardynia\Annotations\Permissions\Acl\Parser\AclParser; use \Doctrine\Common\Annotations\AnnotationReader; use \Doctrine\Common\Annotations\CachedReader; use \Doctrine\Common\Cache\FilesystemCache; class Module implements AutoloaderProviderInterface, ConfigProviderInterface { /** * @var \Zend\Permissions\Acl\Acl */ private $acl = null; public function init(\Zend\ModuleManager\ModuleManager $m){ $event = $m->getEventManager()->getSharedManager(); $event->attach('Zend\Mvc\Application', MvcEvent::EVENT_BOOTSTRAP, function (MvcEvent $e){ $parser = new AclParser(new CachedReader( new AnnotationReader(), new FilesystemCache("/path/to/cache"), $debug = true )); $collector = new AclItemsCollector(new Acl(), $parser); $collector->getAcl()->addRole('guest'); $collector->getAcl()->addRole('admin', 'guest'); $collector->addEntriesFromResourceClass('Album\Controller\AlbumController'); $this->acl = $collector->getAcl(); }); } // other stuff }
您可以在优秀的 [Doctrine Annotations 文档] 中找到有关注解缓存的更多信息(http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html#setup-and-configuration)。
最后思考
这是 ACL 注解包的非常基本的实现,还有很多事情要做,但它在开发环境中可以使用。请随时参与。 :)
待办事项
还有很多事情要做。最重要的有以下几点
- 一个动作使用多个acl注解
- 更灵活的资源类添加
- 定义权限