Real World Access Control
Cake AC is a very powerful but generic access control sytem. Lets face it, the only real use for Access Control is User permissions. So let us look at the common every day use for Access Control.
I'm going to assume we all looked at (and were confused by) the Cake Manual Tutorial on Access Control. I'll also assume you all want to know how you might practically use Cake AC to implement User and Group permissions.
Cake Acces control was not made specifically for User/Group permissions control. It is simply a generic access control system to be used for anything. It can be used for User/Group permissions, but we have a bit of work to do to figure out exactly how.
ARO (Access Request Objects) = Users or Groups
ACO (Access Control Objects) = Your Controllers or Actions
ACL (Access Control List) = List that holds User/Group data access restrictions to Controllers and Actions
So some things of concern here, now that we have this in english.
While Cake AC does not force aliases of anything to be Unique.. well as you might expect, you do run into problems if they are not unique. What will happen if you have a User named 'Smith' and you are putting him into a group called 'Smith'? Well, unless you add something, the system will wonder why you are trying to make 'Smith' a parent of himself.
So with that all said, I set my system up so that references to Users were always made with the users Unique Id (ARO link_id) and references to Groups were made with the Group name (ARO alias)
Download code
The same problem exists with ACO's. If you have your pages treed in controller/action format. When you go to put the home/home (controller/action) page into permisions, well.. the system will wonder why you are trying to make home a parent of itself. I have not figured out how to identify controllers or actions with numbers, so perhaps adding a convention will help.
Download code
So be careful when using Cake access control for User Permissions, it can work, you just have to be careful.
You would never write the following code out (I don't think). Likely you would want a full system where the following data is created using form input from a user.
Download code
In one of your controllers you can do something that looks like this
Download code
After you set up your data, this is practical code, that you might actually write. It will automatically allow or deny the logged in user access to a given action.
Download code
I'll leave it up to you to set up your own permsissions, and groups in a real life system. This does give you a good overview of the concepts though.
There is an ACL management plugin on CakeForge which might help you. Currently it is still young and in development. It might help automate a lot of these things for you.
Cake Acces control was not made specifically for User/Group permissions control. It is simply a generic access control system to be used for anything. It can be used for User/Group permissions, but we have a bit of work to do to figure out exactly how.
Understanding the concepts
How can Cake AC be used for User and Group permissions? Lets simplify things, by talking in terminology that we all understand...ARO (Access Request Objects) = Users or Groups
- link_id = User ID (or 0 if it is a Group)
- parent_id = Id of Group that a User Belongs to
- alias = Unique Id/Name of Users and Groups
ACO (Access Control Objects) = Your Controllers or Actions
- link_id = A Unique Page Id (I have no idea what that is)
- parent_id = Id of Controller that an Action belongs to
- alias = Unique Id/Name of Controlers or Actions
ACL (Access Control List) = List that holds User/Group data access restrictions to Controllers and Actions
- aro = Your user or group
- aco = your controllers or actions
- action = You define the actions, generally read, write, etc..
So some things of concern here, now that we have this in english.
While Cake AC does not force aliases of anything to be Unique.. well as you might expect, you do run into problems if they are not unique. What will happen if you have a User named 'Smith' and you are putting him into a group called 'Smith'? Well, unless you add something, the system will wonder why you are trying to make 'Smith' a parent of himself.
So with that all said, I set my system up so that references to Users were always made with the users Unique Id (ARO link_id) and references to Groups were made with the Group name (ARO alias)
Download code
// set user with id 2 to be part of the group 'admins'
$aro->setParent('Admins', 2);
// just made sure no groups or users ever have numbers for names, and you are safe
The same problem exists with ACO's. If you have your pages treed in controller/action format. When you go to put the home/home (controller/action) page into permisions, well.. the system will wonder why you are trying to make home a parent of itself. I have not figured out how to identify controllers or actions with numbers, so perhaps adding a convention will help.
Download code
// set home action to be a child of the home controller
$aco->setParent('home/home', 'home');
So be careful when using Cake access control for User Permissions, it can work, you just have to be careful.
Putting this into your App
Well, perhaps a real world example of making sure access is controlled would look like this...You would never write the following code out (I don't think). Likely you would want a full system where the following data is created using form input from a user.
Download code
$aro = new Aro(); // users and groups
$aco = new Aco(); // controllers and actions
// add some users and groups to the system
// it is assumed you have your own table of user, with their own information
$aro->create( 1, null, 'John Smith' ); // 1=user_id, null=parent
$aro->create( 2, null, 'Millie Thompson');
$aro->create(0, null, 'Admins'); // group
$aro->create(0, null, 'Managers'); //group
//set John to be an admin
$aro->setParent('Admins', 1);
// set Millie to be an manager
$aro->setParent('Managers', 2);
$aco->create(0, null, 'Home/home');
In one of your controllers you can do something that looks like this
Download code
$this->Acl->allow('Admins', 'Home/home', 'read');
$this->Acl->deny('Managers', 'Home/home');
There, now John can get into home/home and Millie cannot.After you set up your data, this is practical code, that you might actually write. It will automatically allow or deny the logged in user access to a given action.
Download code
class AppController extends Controller {
var $components = array('Acl');
function beforeFilter() {
// next line will change depending on your auth system
// basically getting the Id of the currently logged in user
$user_id = $this->obAuth->getUserId();
$page = $this->name.DS.$this->action;
$access = $this->Acl->check($user_id, $page, 'read');
//access denied (if we are in Home/home, this is Millie)
if ($access === false) {
echo "access denied";
exit;
}
//access allowed (if we are in Home/home, this is John)
else {
echo "access allowed";
exit;
}
}
}
I'll leave it up to you to set up your own permsissions, and groups in a real life system. This does give you a good overview of the concepts though.
There is an ACL management plugin on CakeForge which might help you. Currently it is still young and in development. It might help automate a lot of these things for you.
Comments
Comment
1 The best ACL Tutorial
Comment
2 re the best ACL tutorial
yes! definitely. one of the best starter ACL lessons I've seen. A really good starter position that communicates the parts of ACL most useful to the most people.
Question
3 I Wonder
Comment
4 Further reading...
Most of us have stored hierarchical data with just a parent_id (self join). The above article presents a different and vastly more optimal way to do this, but it's hard to wrap the brain around. In any event, that article explains how the hierarchy is mapped in cakePHP
Comment
5 I Wonder Reply
https://trac.cakephp.org/ticket/2191
Comment
6 Re. Further reading...
See http://api.cakephp.org/1.2/class_tree_behavior.html
Bug
7 Great article
I did notice one bug (I think). In the last section, you have written:
$page = $this->name.DS.$this->action;
$access = $this->Acl->check($page, $user_id, 'read');
In the check function, I believe $page (an ACO) should be switched with $user_id (an ARO). Not 100% on this, but I think it's a small bug.
Anyway, great article!
Comment
8 reply to Great Article
Question
9 Im sure this is retardedness on my part
Except, apparently, the "understand" part.
Regarding CakePHP 1.2. Questions:
1) The acl.php lib that contains the Acl class actually contains only a "AclComponent" class. Is this what is being used in Cake 1.2?
2) If yes to (1), then how are the $acl, $aco objects instantiated (or are they)? Something like
$acl = new AclComponent();
$aro = new $acl->Aro(); // this? or
// Create aro
$acl->Aro->create(1,null,'Admin Guy');
Confused!!
3) I tried fifty different combinaations of the code on this page and the code in (2) in my comment here and still have no aros created in my aro table.
I really am lost on this thing; nothing seems to be working. Arrgh!
Comment
10 Please help me to know about ACL
Comment
11 ACM on CakeForge
Comment
12 Very beautiful Tutorial.
"Cake Acces control was not made specifically for User/Group permissions control. It is simply a generic access control system to be used for anything."
I might have not taken that much time thinking about the basic ACL design if I saw your stuff earlier.
As a complement, I understood the ACL by dividing the concepts for typical uses into two genres:
1. For Controller/Action level verification, which was summarized in this article.
2. For Record level verification, which usually use something like 'Model::id' as an alias to identify an aCo.
Finally, ACL is nothing but relations between tree-structured records. What is aRos, what is aCos, when will the objects be used and where will they be checked are full charged by designers.
Question
13 Cannot Inherting Permission
But I found a problem that, I think it cannot inherit permission from one group to other group.
Like if I have two groups under the root i.e
ROOT
1 admin
2 member
and suppose i have an acos
/
1 Posts/
2 Posts/lists
I have member test under admin group.
Now if I deny the permission to ROOT for acos Posts/lists or /
then acl will not inherit this permission to users test and it allow the access to Posts/lists
Is it not possible with acl?
if yes, please suggest how to do?
Also I want if permission to acos '/' is denied for any group then none of the resources should be accessible to that group unless and untill i assign the permsion to that group