最近发现自己的效率特别低,不知是什么原因。今天只完成了ACL 插件的编码,总结来讲,总共学到了两个知识点。
第一、关于插件,zend framework 使用插件来辅助请求从开始到结束的各个阶段的一些工作
插件文件一般放在libarary/zend/controller/plugin/文件夹下,类的名称为zend_controller_plugin_acl,当然这是今天项目用到的。在该文件夹下建立acl.php文件。zend_controller_plugin_acl继承Zend_Controller_Plugin_Abstract。为了对应请求的不同时间段,需要用不同的函数。preDispatch---今天项目用到的,还有几个函数,在上上篇文章里有提及,不再赘述。
<? public function preDispatch(Zend_Controller_Request_Abstract $request) { $rolename= $this->getRoleName(); $acl=$this->_getAcl(); $moduleName =$request->getModuleName(); $controller = $request->getControllerName(); $action=$request->getActionName(); //这里省略n多内容
$request 就是指本次请求的对象
写好方法后需要在前端,即bootstrap或者index.php里面注册插件。不知为何,我在boostrap.php,_initi()里面没有成功。在index.php里面成功了。
Zend_Controller_Front::getInstance()->registerPlugin(new Zend_Controller_Plugin_Acl());
然后上面部分代码就会在分发动作开始前行动了。
第二、关于Acl
这部分内容费了我大多数的时间,主要是疑问太多,到现在还要一个地方的疑问没有解决
这里不得不感谢google,帮了我不少忙,百度里面抄袭的现象太严重...哎,看来技术类问题还得去google,特别是今天发现了国外的一个技术问答类网站,stackoverflow,做得够专业。我今天遇到的问题,里面都有人讨论。有时间得常去看看。----废话停...。。。
在stackoverflow里面讨论ACL访问控制问题有一段很好的解答,思路是用ini文件存储访问控制信息。
这里摘抄一下,以免将来找不到。。。
数据库====
1 CREATE TABLE IF NOT EXISTS `USER` ( 2 `user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 3 `email` VARCHAR(85) NOT NULL , 4 `password` CHAR(32) NOT NULL, 5 `phone` VARCHAR(45) NULL , 6 `phone_public` TINYINT(1) NULL DEFAULT 0 , 7 `first_name` VARCHAR(45) NULL , 8 `last_name` VARCHAR(45) NULL , 9 `last_name_public` TINYINT(1) NULL DEFAULT 1 , 10 `is_enabled` TINYINT(1) NOT NULL DEFAULT 1 , 11 `created` TIMESTAMP NOT NULL, 12 `privilage` ENUM('BASIC','PREMIUM','ADMIN') NOT NULL DEFAULT 'BASIC' , 13 PRIMARY KEY (`user_id`) , 14 UNIQUE INDEX `email_UNIQUE` (`email` ASC) ) 15 ENGINE = InnoDB;
acl.ini (I have four privileges, such that basic inherits from guest, premium inherits form basic and administrator for premium):
; roles acl.roles.guest = null acl.roles.basic = guest acl.roles.premium = basic acl.roles.administrator = premium ; resources acl.resources.deny.all.all = guest acl.resources.allow.index.all = guest acl.resources.allow.error.all = guest acl.resources.allow.user.login = guest acl.resources.allow.user.logout = guest acl.resources.allow.user.create = guest acl.resources.allow.user.index = basic acl.resources.allow.user.success = basic
My_Acl class (creates acl roles and recurses based on the ini file):
1 class My_Acl extends Zend_Acl { 2 3 public function __construct() { 4 $aclConfig = Zend_Registry::get('acl'); 5 $roles = $aclConfig->acl->roles; 6 $resources = $aclConfig->acl->resources; 7 $this->_addRoles($roles); 8 $this->_addResources($resources); 9 } 10 11 protected function _addRoles($roles) { 12 13 foreach ($roles as $name => $parents) { 14 if (!$this->hasRole($name)) { 15 if (empty($parents)) { 16 $parents = null; 17 } else { 18 $parents = explode(',', $parents); 19 } 20 $this->addRole(new Zend_Acl_Role($name), $parents); 21 } 22 } 23 } 24 25 protected function _addResources($resources) { 26 27 foreach ($resources as $permissions => $controllers) { 28 29 foreach ($controllers as $controller => $actions) { 30 if ($controller == 'all') { 31 $controller = null; 32 } else { 33 if (!$this->has($controller)) { 34 $this->add(new Zend_Acl_Resource($controller)); 35 } 36 } 37 38 foreach ($actions as $action => $role) { 39 if ($action == 'all') { 40 $action = null; 41 } 42 if ($permissions == 'allow') { 43 $this->allow($role, $controller, $action); 44 } 45 if ($permissions == 'deny') { 46 $this->deny($role, $controller, $action); 47 } 48 } 49 } 50 } 51 } 52 53 }
My_Controller_Plugin_Acl:
1 class My_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract { 2 3 /** 4 * 5 * @var Zend_Auth 6 */ 7 protected $_auth; 8 9 protected $_acl; 10 protected $_action; 11 protected $_controller; 12 protected $_currentRole; 13 14 public function __construct(Zend_Acl $acl, array $options = array()) { 15 $this->_auth = Zend_Auth::getInstance(); 16 $this->_acl = $acl; 17 18 } 19 20 public function preDispatch(Zend_Controller_Request_Abstract $request) { 21 22 $this->_init($request); 23 24 // if the current user role is not allowed to do something 25 if (!$this->_acl->isAllowed($this->_currentRole, $this->_controller, $this->_action)) { 26 27 if ('guest' == $this->_currentRole) { 28 $request->setControllerName('user'); 29 $request->setActionName('login'); 30 } else { 31 $request->setControllerName('error'); 32 $request->setActionName('noauth'); 33 } 34 } 35 } 36 37 protected function _init($request) { 38 $this->_action = $request->getActionName(); 39 $this->_controller = $request->getControllerName(); 40 $this->_currentRole = $this->_getCurrentUserRole(); 41 } 42 43 protected function _getCurrentUserRole() { 44 45 if ($this->_auth->hasIdentity()) { 46 $authData = $this->_auth->getIdentity(); 47 $role = isset($authData->property->privilage)?strtolower($authData->property->privilage): 'guest'; 48 } else { 49 $role = 'guest'; 50 } 51 52 return $role; 53 } 54 55 }
Finally a part of Bootstrap.php where everything is initialized:
1 protected function _initLoadAclIni() { 2 $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/acl.ini'); 3 Zend_Registry::set('acl', $config); 4 } 5 6 protected function _initAclControllerPlugin() { 7 $this->bootstrap('frontcontroller'); 8 $this->bootstrap('loadAclIni'); 9 10 $front = Zend_Controller_Front::getInstance(); 11 12 $aclPlugin = new My_Controller_Plugin_Acl(new My_Acl()); 13 14 $front->registerPlugin($aclPlugin); 15 }
好了,复制完毕--
这里遇到一个问题,关于module-coMIntroller-action三级精细控制问题。ACL的allow('role','resource','action')方法中并不能将resource分开....因此实现resource的module和controller分开真的是有点难度。。。哎....待续吧,等想到好方法再写,目前用的就是看到的那个将module.controller当做资源标志....