Access control: Why not a helper?
Every single ACL tutorial I’ve seen (not that I’ve seen many) uses controller plugins to check access to pages. People seem to be forgetting that action helpers have a preDispatch() method too, and in some ways it really makes sense to stuff ACL checking in there rather than in a plugin.
Since we’re controlling access to a controller action, doesn’t it make sense to know if the controller or action exists in the first place? Plugins are not controller-aware. In fact, the controller object doesn’t exist yet during plugin preDispatch()! If your ACL plugin happens to use a database backend, an invalid request means unnecessary database hits. Sure, you can invoke the dispatcher’s isDispatchable() method, but why do that in the plugin when the dispatcher does exactly the same shortly after the plugin preDispatch()? Since most of your requests are indeed valid, querying the dispatcher in the plugin preDispatch means an additional superfluous file stat per request. Not that I advocate micro-optimizations like these, but still… I think it’s just better to fit your code into the framework than altering the flow of events in the framework to fit your code.
It is desirable sometimes to manipulate the ACL checker at a per-controller basis. For example, one might want to disable access control on a certain controller if the user comes from a specific IP. You could probably write a permission for that special case, but it’s much simpler to just disable checking when the request hits that controller and the conditions are satisfied. The controller init() method is the perfect place to add these exemptions since it is executed right before the helper preDispatch(). In addition, you could do stuff like adding access rules to the ACL object or embed the access rules as public properties of the controller, like I do in my ACL implementation (see below). Again, you can’t do this in a plugin naturally since the controller object hasn’t been instantiated yet during the plugin preDispatch().
And finally, action helpers are easily invokable inside controller actions. It is very likely that you would want to query the ACL object inside controller actions. Your ACL object doesn’t necessarily have to be limited to permissions for controller actions. You can also set permissions for your model objects. With a helper, you can very easily pull out the ACL object and ask if the user is allowed access to a certain object. With a plugin, you probably have to assign the object to the evil registry first in order to access it in the controller.
I have put my ACL/auth implementation up in googlecode. Visit the project page and hit source->browse or download the package for an example on how to implement an action helper ACL checker.
Hi! Great article.
I prefer to manage acl in my service layer. I create a service “AclService” which use a Zend_Acl object. The AclService is called by the other services. I use this AclService in my controllers only when it’s “view” related (like displaying a navigation button if the user is admin). With this technique i can easily create an “acl-aware” api (webservice) for my application