对于一个应用来说,不仅仅有控制器和动作方法。有时候,你会想允许某个用户访问某个控制器和动作,但是又想让他仅仅只能操作系统中属于他的内容对象。例如,我们允许用户修改博文,但是只能修改他自己的博文。在这些应用中,我们需要知道当前用户正在操作的博文的所有者是否是他。
首先,你必须在内容对象中创建特定的方法。在此示例中,我们将创建accessIsOwner()
方法,当然方法名可以随便取。
这个内容对象中的特殊的所有权方法按顺序接受两个参数:一个是Solar_Auth_Adapter的实例,另一个是Solar_Role_Adapter的实例。那么你刚才写的这个方法就可以当前检验用户的身份认证和/或角色,最后如果该用户被认定为该内容对象的所有者,则返回真值。(否则,返回假值。)
作为一个示例,假设我们有一个博文的模型记录,并且对应于此模型的数据表有一个author_handle
字段(也即,该博文的创建者的用户名)。我们可以在博文记录类中写下这个方法:
<?php
class Vendor_Model_Blogs_Record
{
public function accessIsOwner(Solar_Auth_Adapter $auth, Solar_Role_Adapter $role)
{
// check the record's 'author_handle' column to see
// if it matches the current authenticated user.
if ($this->author_handle == $auth->handle) {
return true;
}
// not the original author, so don't treat as an owner.
return false;
}
}
对于系统中的每一种内容对象,你必须告诉Solar_Access_Adapter适配器在决定当前用户是否是所有者时使用何种方法。在上面的示例中,我们写了一个Vendor_Model_Blogs_Record::accessIsOwner()
方法。接下来我们在配置文件中为Solar_Access_Adapter
写一条配置项:
<?php
$config['Solar_Access_Adapter']['owner_method'] = array(
'Vendor_Model_Blogs_Record' => 'accessIsOwner',
);
'owner_method'
配置项的值是是一个键-值对关联数组,键代表被检验的内容对象的类名,值代表该类中的检验方法。之后当我们调用$user->access->isOwner()
方法的时候,适配器将遍历数组中的这些键来匹配当前控制器对象,并且调用相关的方法来检验所有权。
在之前的某一节当中提到过,在控制器和动作中检验权限时,你可以使用'owner'
记录类型指定当前用户必须为该对象的所有者。
# flag type name class action # ---- ---- ---- ----- ------ # allow users to edit their own posts allow owner - Vendor_App_Blog edit
现在,我们在内容对象中已经有一个特有的所有权方法了,并且访问适配器知道使用何种方法去检验内容对象。我们可以在控制器动作中使用所有权访问验证了。
使用前面提到的“动作内部的访问控制”方法,在动作中加所有权验证的代码如下:
<?php abstract class Vendor_Controller_Page extends Solar_Controller_Page { public $user; protected function _setup() { parent::_setup(); $this->user = Solar_Registry::get('user'); } protected function _isUserAllowed($object = null) { if ($this->user->access->isAllowed($this, $this->_action, $object)) { return true; } else { $this->_error('Access denied.'); $this->_response->setStatusCode(403); return false; } } } class Vendor_App_Blog extends Vendor_Controller_Page { public function actionEdit($id = null) { // ... perform preliminary logic ... // get the blog item for editing $item = $this->_model->blogs->fetch($id); // check access if (! $this->_isUserAllowed($item)) { return; } // ... rest of the action here ... } }
-
在
_isUserAllowed()
方法中,我们加了一个参数用于传递需要进行所有权验证的内容对象。类似的,isAllowed()
方法也要传递需要验证的内容对象。 -
actionEdit()
方法在验证访问控制权限之前获取博文记录。在博文获取之后,我们才验证在当前控制器和动作中用户是否允许访问内容对象。