新随笔  :: 联系 :: 订阅 订阅  :: 管理

Zend_Acl

Posted on 2012-04-27 00:07  张贺  阅读(1140)  评论(0编辑  收藏  举报

Zend_Acl的误解

很多人会误认为ACL的resource和privilege是controller和action,这是错误的。

对Zend_Acl而言,resource可以是任何事物-一个controller,一个file,一个module...
privilege就像resource一样,也可以是任何与resource相关的事物,例如,如果resource是一个controler,那privilege就可以是一个action,或者如果controller是一个file或者model,那么它就可能是read或者write。

创建一个简单的ACL
前面提到,Zend_Acl是由资源(resources)、权限(privileges)和角色(roles)构成的。privileges是访问resources的权限级别。roles就是以指定的访问权限(privilege)来访问resource的访问对象,可以是一个用户,用户组or anything you wish to associate such data with。

下面是一个ACL的简单代码,只包含了少量的resources和roles

 1 class My_Acl extends Zend_Acl {
 2   public function __construct() {
 3     //Add a new role called "guest"
 4     $this->addRole(new Zend_Acl_Role('guest'));
 5  
 6     //Add a role called user, which inherits from guest
 7     $this->addRole(new Zend_Acl_Role('user'), 'guest');
 8  
 9     //Add a resource called page
10     $this->add(new Zend_Acl_Resource('page'));
11  
12     //Add a resource called news, which inherits page
13     $this->add(new Zend_Acl_Resource('news'), 'page');
14  
15     //Finally, we want to allow guests to view pages
16     $this->allow('guest', 'page', 'view');
17  
18     //and users can comment news
19     $this->allow('user', 'news', 'comment');
20   }
21 }

 

此时创建一个My_Acl的实例,就可以对应一些简单的权限对应设定,但是具体那个角色拥有什么权限呢?

guest角色对于page资源拥有一个view的权限,之后user角色继承了guest,所以user也拥有了page的view权限。news资源继承了page,所以所有用户对news资源都拥有与对page资源相同的权限。在构造函数的最后一行,我们为user角色在news资源上新增了一个comment的权限。而此时只有user角色拥有news资源的comment权限,guest没有。

使用ACL
使用一个ACL类非常简单。你只需要调用isAllowed方法,同时向它传递一个role,resource和一个privilege参数既可。而最大的难点在于你如何确定哪个是role, resource和privilege。

该如何确定哪个是角色?一个非常简单的假设就是:如果这有一个登陆用户user,那么这个角色就是user,否则就是guest。

那么资源呢?这取决于你的应用程序,这可以从你所包含的文件名中猜测出来。例如:对于上面的例子中,我们有一个page.php文件和一个news.php文件用来对应于page资源,而news对应于news资源。


最后什么是权限呢?当我们简单的读取page的时候,你可以使用view权限。稍后代码会检测一些其它一些权限规则,例如comment权限以及显示comment box的权限等。

下面是一个简单的实例

1 $role = 'guest';
2 if(isset($_SESSION['auth']))
3 $role = 'user';
4 
5 $acl = new My_Acl();
6 
7 if($acl->isAllowed($role, 'news', 'comment')) {
8 //Some code here to display a news box
9 }

在ZF项目中使用ACL
在zf项目中,资源和权限通常会在请求资源中确定。
通常我们可以创建一个检测权限的插件:

 1 class My_Plugin_Acl extends Zend_Controller_Plugin_Abstract {
 2   private $_acl = null;
 3  
 4   public function __construct(Zend_Acl $acl) {
 5     $this->_acl = $acl;
 6   }
 7  
 8   public function preDispatch(Zend_Controller_Request_Abstract $request) {
 9     //As in the earlier example, authed users will have the role user
10     $role = (Zend_Auth::getInstance()->hasIdentity())
11           ? 'user'
12           : 'guest';
13  
14     //For this example, we will use the controller as the resource:
15     $resource = $request->getControllerName();
16  
17     if(!$this->_acl->isAllowed($role, $resource, 'view')) {
18       //If the user has no access we send him elsewhere by changing the request
19       $request->setModuleName('auth')
20               ->setControllerName('auth')
21               ->setActionName('login');
22     }
23   }
24 }

 

我们可以在上面的例子中创建一个静态方法来代替构造函数。
将上面的插件加载到前段控制器中:

1 $acl = new My_Acl();
2 
3 //assuming $fc is the front controller
4 $fc->registerPlugin(new My_Plugin_Acl($acl));

 

此时每个请求都会核对权限控制列表,并且没有view权限的角色将会别拒绝访问。
接下来就是关于如何检测comment权限
在需要检测comment权限的controller中添加一些代码来向view中传递一个boolean值来确定权限。

1 public function someAction() {
2 $role = (Zend_Auth::getInstance()->hasIdentity())
3 ? 'user'
4 : 'guest';
5 
6 //assuming $this->_acl contains the acl
7 $this->view->canComment = $this->_acl->isAllowed($role, 'news', 'comment');
8 }

创建自定义角色类
通过扩展Zend_Acl_Role_Interface接口来定义角色类,使其具有更多的灵活性。该接口只包含一个方法getRoleId()

 1 class Common_Module_acl_user implements Zend_Acl_Role_Interface
 2 {
 3     protected $_name;
 4     
 5     public function __construct($name)
 6     {
 7         $this->_name = $name;
 8     }
 9     
10     public function getRoleId()
11     {
12         return 'user_'. $this->_name;
13     }
14 }

此时只需将该类的实例传递给Zend_Acl对象既可

1 $acl = new Zend_Acl();
2 //添加一个名为user_zh的角色
3 $acl->addRole(new Common_Module_acl_user('zh'));

 

创建自定义资源类
通过扩展Zend_Acl_Resource_Interface接口来实现自定义资源类

1 class Resource_Controller implements Zend_Acl_Resource_Interface {
2     public function __construct($id) {
3       $this->_id = $id;
4     }
5  
6     public function getResourceId() {
7       return 'controller-' . $this->_id; 
8     }
9 }

实现方法同角色类一样

PHP技术交流群 170855791