Zend Framework: ACLs for users with multiple roles

(The following is a guest post by Doug Bierer, one of our instructors for the Zend Framework training courses)

After covering the essentials of the Zend\Permissions\Acl component (Access Control unit, Cross Cutting Concerns module, in the Zend Framework Advanced course), many students have approached me to ask, “what happens if a user has multiple roles?”

In this article I discuss the “traditional” way of handling a user who has multiple roles, and then lay out an easy approach which I simply call Mr. X.

Background on Access Control Lists

As you may (or may not) know, the Zend\Permissions\Acl component uses three elements to define rights:

  • Role
  • Resource
  • Rights

Assuming we use controllers as resources, and actions as rights, here is a typical Access Control List (ACL) for a company having departments of Sales, Marketing, Support. In this case we can use the department as the role, so the ACL might look something like this:

Don’t Forget Everyone

So far so good! Oops … right away we have a problem: what about website visitors who we want to allow access to the home page? Also, what about login? OK, let’s assume, for the sake of illustration, that the IndexController::indexAction produces the home page, and the loginAction takes care of login. One possibility would be to define a constant which represents a new role everyone, and to have all roles inherit from that. So we make these modifications to the example above:

and

So now our class looks like this:

But What About Bob?

But wait … we forgot about Josie, who is in both Sales and Marketing. And then there’s Bob, who is in Support and Sales.

We could create a new role SalesMktg which inherits from both Sales and Marketing … but then we’d have to add an if statement which checks to see if, after authentication, that user belongs to both departments. Likewise, we could add a new role SalesSupport which inherits from both Sales and Support … but this means another if statement, and so on and so forth.

Another option would be to create a method multiCheck($roles, $resource, $right) in our ACL class which loops through all the departments, and checks to see if that role has rights or not. Maybe something like this:

But that kind of ruins the simplicity of the Access Control List, and further, fails to take advantage of its already built-in multi-inheritance. In short, things can start to get messy very quickly in this situation.

Introducing Mr. X

The concept of Mr. X is astonishingly simple. The idea is that anybody who visits the website, no matter who they are, assumes the role of MR_X. We then check the results of Zend\Authentication\AuthenticationService::getIdentity() where (presumably) we have stored a field department (to follow this example: otherwise the field could be called groups, or even just roles). We will further assume that this field is in the form of an array, even if the user only belongs to one department.

In this scenario, we don’t worry about having other roles inherit from everyone: we will automatically add it as a parent from which MR_X inherits. Here is what we add to the ACL to support MR_X:

Here is how our finished ACL appears:

We’re now ready to Rock N Roll! First let’s slap together a little stand-alone test program:

We can test for non-authenticated users, to see if they can hit the home page:

Hooray, it works! But can somebody in Sales access the home page?

Excellent! Now let’s run some other tests:

And there you have it. From now on, anywhere in your application, all you need to do is to do an Acl::isAllowed() against MR_X and you’re good to go.

To learn more about our Zend Framework and other training courses, visit our website.

The following two tabs change content below.
    Roy figured that the best way to learn something is to try and explain it to someone else. After years of explaining things while standing up, he decided the better approach was to do it while sitting down. Beside a poster of a famous starship. Learning from projects in defense, mobile, and game development, Roy figured out one more thing: real code isn't dead but it could be made better.

    About Roy Sarkar

    Roy figured that the best way to learn something is to try and explain it to someone else. After years of explaining things while standing up, he decided the better approach was to do it while sitting down. Beside a poster of a famous starship. Learning from projects in defense, mobile, and game development, Roy figured out one more thing: real code isn't dead but it could be made better.