海角不转弯

代码是梦想的砖

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

最近发现自己的效率特别低,不知是什么原因。今天只完成了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当做资源标志....

posted on 2013-04-18 23:36  海角不转弯  阅读(184)  评论(0编辑  收藏  举报