我使用以下方案。值得一提的是,大多数用户权限检查可以分为两种一般情况:
- 用户根据用户角色访问控制器操作,而无需检查参数操作,
- 用户根据特定用户与特定模型之间的任何逻辑或关系访问模型。
通常在MVC框架中实现对控制器动作的访问而不检查属性。这一点很简单:您定义规则,您的用户就可以扮演角色。您只需检查用户是否有权进行操作来查找其在规则中的角色。
用户对特定模型的访问应在模型中定义。(Actor是基本用户类。假设它可以是客户,卖方或访客。)
interface ICheckAccess
{
public function checkAccess(Actor $actor, $role);
}
class SomeModel implements ICheckAccess
{
public function checkAccess(Actor $actor, $role)
{
// Your permissions logic can be as sophisticated as you want.
}
}
将逻辑放在模型中会带来一些好处。访问检查方法可以被继承,您不需要创建任何额外的类,就可以使用常规的OOP优势。
接下来,为了简化访问检查,为了简单起见,我们采取一些假设,这些假设几乎总是已经实现:
- 通常,控制器与某些模型类相关;
- 检查访问的操作以单个模型ID作为参数;
- 始终可以从基本控制器类的方法统一访问此参数;
- 动作放置在与ID动作所采用的模型相对应的控制器中。
通过这些假设,可以将使用模型ID的动作与特定的模型实例相关联。实际上,大多数动作都可以轻松地转换和移动以适应上述假设。
然后,应该定义和继承一些基本的抽象控制器类。
abstract class ModelController
{
// Retrieve model from database using id from action parameter.
public abstract function loadModel($id);
// Returns rules for user role to pass to SomeModel::checkAccess()
// Something like array('view' => 'viewer', 'delete' => 'owner', 'update' => 'owner')
public abstract function modelRules();
public abstract fucntion getIdParameter();
public function filterModelAccess()
{
$id = $this->getIdParameter();
if(!$this->checkModelAccess($id))
throw new HttpException(403);
}
public function checkModelAccess($id)
{
$model = $this->loadModel($id);
$actor = My::app()->getActor();
$rules = $this->modelRules();
$role = $rules[My::app()->getActionName()];
return $model->chechAccess($actor, $role);
}
}
您可以在构造菜单并决定是否显示某些链接时调用SomeController :: checkModelAccess($ id)方法。