访问控制设计模式

Eve*_*ert 5 authorization design-patterns access-control rbac abac

我正在开发PHP应用程序,我想为某些对象添加访问控制。我没有将此问题标记为PHP,因为我认为该问题不是特定于语言的。

说我有一个“服务等级”

abstract class Service {


}
Run Code Online (Sandbox Code Playgroud)

许多服务都将此作为基类。一个伪示例为:

class Companies extends Service {

  function getCompanyInfo($id) {
      //...
  }

}
Run Code Online (Sandbox Code Playgroud)

稍后,我要添加访问控制。示例的“ getCompanyInfoById”方法是“读取”操作,因此这将需要“读取”权限。

此时,我可以通过以下方式实现此目的:

  1. 将accesscontrol添加到Service类。在完成操作并返回结果之前,每个方法(例如getCompanyInfoById)都必须在内部调用“ hasPrivilege”方法。
  2. 将所有Service对象包装在某种Proxy对象中,该对象将在调用内部对象中的方法之前检查特权。
  3. 完全独立的访问控制,并在调用方法之前强制“调用方”检查特权。

每个选项的缺点:

  1. 这要求更改所有服务,并要求他们了解访问控制。我认为这与关注点分离背道而驰。
  2. 这会破坏OOP功能,例如多态。呼叫者不再知道任何服务支持什么接口。
  3. 这是最灵活的方法,但是最大的缺点是检查权限现在是隐式的。开发人员可以“忘记”或复杂的代码路径可能导致未经授权的服务被调用。

是否有更好的方法可以完全解决此问题?

Dan*_*eti 3

另一种解决方案可能是您的解决方案 1 的一个小变体。

前任。

class Service
{
  var $ACL = //some hash map with acl
}

class Companies extends Service
{

  function getCompanyById($id)
  {
    //real code
  }
}

class SafeCompanies extends Companies
{
//If a method must be "protected" with an ACL, you must override them in this way
  function getCompanyById($id)
  {
    $this->check('read'); //raise an exception if current user haven't READ privilege
    parent::getCompanyById($id);    
  }  
} 
Run Code Online (Sandbox Code Playgroud)

这样你就不会混合职责并且仍然可以使用多态性

我的 2 美分