English 中文(简体)
Access control design patterns
原标题:

I m working on a PHP application, and I d like to add access control to some of my objects. I didn t tag this question as PHP, as I feel this question is not language specific.

Say I have a Service class

abstract class Service {


}

Many services use this as a baseclass. One pseudo example would be:

class Companies extends Service {

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

}

Later down the road I want to add access control. The example getCompanyInfoById method is a read operation, so this would require a read privilege.

At this point I can implement this in the following way:

  1. Add accesscontrol to the Service class. Every method (such as getCompanyInfoById) must call the hasPrivilege method internally before completing the operation and returning the result.
  2. Wrap all Service objects in a some kind of Proxy object that will checks privileges before calling the method in the inner-object.
  3. Completely separate access control, and force the caller to check privileges before calling the method.

Cons for every option:

  1. This requires changing all Services, and requires them to be aware of Access control. I feel this goes against Separation of concerns.
  2. This breaks OOP features, such as Polymorphism. The caller no longer knows what interfaces any service supports.
  3. This is the most flexible, but the big drawback is that checking permission is now implicit. Developers can forget or complex codepaths can cause unauthorized services to be called.

Are there better ways to approach this altogether?

最佳回答

Another solution could be a little variant of your 1.

ex.

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);    
  }  
} 

in this way you dont mix responsibilities and still can use polymorphism

my 2 cents

问题回答

The Java EE model is pretty much on the lines of 2. Your code runs in a "Container", you tell the container about your interface entry points (URLs for servlets, methods for EJBs) and define the roles that can use these entry points. An adminstrator maps the authentication info (eg. LDAP user and groups) to specific roles and the container consults that mapping in granting access to the entry points.

The key here is that the Container "knows" about your code, it s effectively a quite clever proxy.

In the absence of a container I d be looking at the proxy approach, perhaps using some kind of Aspect Oriented technique.

I think you re right that option 3 is very brittle,too much responsibility on the client programmers.

Ten years later... The world has evolved quite a bit since and in particular a whole new paradigm has come up: externalized authorization. To be fair, each and every development framework has its own version of it (e.g. CanCanCan in Ruby or Spring Security in Java or Claims-based authorization in C#). Externalized authorization aims to decouple authorization logic from business logic. The idea is that authorization needs might evolve independently of business logic. For instance your business logic provides access to bank accounts (view / edit / delete / transfer). The functionality is stable - it won t change in the near future. However, the authorization needs might evolve because of legislation (GDPR, Open Banking...) or different requirements (delegation, parent-child, VIP...) This is why you want to maintain authorization externally.

To do so, there is a model called attribute-based access control () which is an evolution / extension to the more well-known role-based access control (). In RBAC, access control is identity-centric. It is based on the user, the role, and the group(s) the user belongs to. That s not enough often times. In ABAC, you can use attributes of the user, resource, context (time), and action. ABAC also lets you write policies in plain old English using standardized policy languages ( or or Rego). The cloud platforms (AWS and Google) have also implemented their own language (Called Google IAM and AWS IAM respectively).

Some of the benefits of ABAC are:

  • flexibility: you can change your authorization policies without touching your apps / APIs
  • reusability: you can apply the same policies to data, APIs, apps, or infrastructure.
  • visibility: express authorization as policies rather than hard-code the logic which means you can easily audit the policies and understand what is possible / what isn t
  • auditability: with ABAC you get a single log of all access that was granted or denied.

If you want to learn more, check out the Wikipedia pages for ABAC and ALFA as well as NIST s page on ABAC.





相关问题
Choosing the right subclass to instantiate programmatically

Ok, the context is some serialization / deserialization code that will parse a byte stream into an object representation that s easier to work with (and vice-versa). Here s a simplified example ...

Design pattern for managing queues and stacks?

Is there a design pattern for managing a queue or a stack? For example, we are looking to manage a list of tasks. These tasks will be added to a group queue, users will then be able to pull off the ...

Organizing classes using the repository design pattern

I have started upgrading one of our internal software applications, written in ASP.NET Web Forms, and moving to ASP.NET MVC. I am trying to leverage the Repository design pattern for my classes, ...

Misuse of Observer Pattern?

I have a Car object which contains a latitude field and a longitude field. I use the observer pattern so that any time either of these fields change in my application, my car object is notified. I ...

How are Models (in MVC) and DAOs supposed to interact?

How are models and DAOs supposed to interact? I m in the process of putting together a simple login module and I m unsure where to put the "business logic." If I put the logic with the data in the ...

热门标签