Page 1 of 1
Simplistic Access Control
Posted: Fri Dec 12, 2008 5:27 pm
by VirtuosiMedia
I've never used access control before, but I'm at a point where I need it. I've taken a look at Cake and Zend's ACL components, but I don't quite understand everything that they're doing or why they need everything they have. I've written my own access control classes below. They work, but since I've never used access control, I'm not sure if this is way too simplistic and what capabilities I might be missing or what problems I might run into. If you have any suggestions or comments, please share.
Edit: I altered it quite a bit, so please reference my next post.
Re: Simplistic Access Control
Posted: Fri Dec 12, 2008 7:42 pm
by Christopher
I am not exactly clear on what you mean my be term "consumer" I am familiar with the term "resources" in the context. Usually it is Resources, Permissions (for each Resource) and then Groups/Roles/whatever. All this code seems to be doing is seeing if an number is in an array. Can you describe more what your consumers, resources and identities are?
Re: Simplistic Access Control
Posted: Fri Dec 12, 2008 9:39 pm
by VirtuosiMedia
Okay, so I made some changes. I'm not completely sure on my naming scheme yet, but I'll try to explain as best as I can. There are three types of Acl objects, all based on the Vm_Acl class below:
Consumer - An object that tries to access a resource
Resource - An object that encapsulates permission-based resources or actions
Resource/Consumer - A resource object that can also consume other resources
Here is my new Acl class:
Code: Select all
class Vm_Acl {
protected $id = NULL;
protected $resourceList = array();
protected $consumables = array();
/**
* @param mixed $id - The consumer id
*/
function __construct($id){
$this->id = $id;
}
/**
* @return mixed - The consumer id
*/
public function getId(){
return $this->id;
}
/**
* Description: Sets the list of resources a potential consumer object can consume
* @param array $resourceList - An array of resources accessible to the consumer
*/
public function setResourceList(array $resourceList){
$this->resourceList = $resourceList;
}
/**
* Description: Gets the list of resources a potential consumer object can consume
* @return array $resourceList - An array of resource ids accessible to the consumer
*/
public function getResourceList(){
return $this->resourceList;
}
/**
* Description: Sets a list of resource ids the object can consume
* @param array $consumerResourceList - An array of resource ids to which a consumer Acl object has access
*/
public function setConsumables(array $consumables){
$this->consumables = $consumables;
}
/**
* Description: Gets a list of resource ids the object can consume
* @return array $consumerResourceList - An array of resource ids to which a consumer Acl object has access
*/
public function getConsumables(){
return $this->consumables;
}
/**
* @return boolean - TRUE if the consumer object has access to consume the current object's resources, FALSE otherwise
*/
public function accessPermitted(){
return (in_array($this->id, $this->resourceList)) ? TRUE : FALSE;
}
}
Here is a sample resource:
Code: Select all
class Blog extends Vm_Acl {
function __construct(array $resourceList){
parent::__construct('blog');
$this->setResourceList($resourceList);
}
public function getPost(){
return ($this->accessPermitted()) ? 'A full blog post would go here' : 'Access Denied';
}
}
And here is the example use case:
Code: Select all
//The consumerId would be a foreign key in the users table
$consumerId = 34;
// $user in this case will be a consumer object
$user = new Vm_Acl($consumerId);
/*
* Here we would access the database and get all of the of the resources
* that can be accessed (or consumed) by the consumerId and then we would
* put them the consumables array
*/
$consumables = array('blog', 'forum');
//Now we set the list of consumable resources for $user
$user->setConsumables($consumables);
/*
* $blog is a resource object in this example. Here we are passing it the
* list of resources $user has access to. If 'blog' is on the list, then the
* $blog object is deemed accessible to $user
*/
$blog = new Blog($user->getConsumables());
// Echoes the blog post if the user has access, denies access otherwise
echo $blog->getPost();
In order to prevent needless queries, one query should be run to get all of the resources a consumer is able to access. The resource names are then put into an array which is marked $consumables and is given to our $user object, which is the consumer in this case. Next, we instantiate the Blog object and pass it a list of resources $user is able to access. From that point on, there is no need to pass along any more permissions to the Blog object. Any subsequent Acl resource objects wouldn't require any more hits to the database either because they could just be passed $user's consumables.
With this setup, any object extending the Acl object could be a consumer, a resource, or both.
Re: Simplistic Access Control
Posted: Fri Dec 12, 2008 10:20 pm
by josh
Generally speaking, with ACL I want to be able to define role like
guest;
writer extends guest;
editor extends writer;
grant * to writer // also grants * to editor by definition
Re: Simplistic Access Control
Posted: Sat Dec 13, 2008 4:09 pm
by VirtuosiMedia
jshpro2 wrote:Generally speaking, with ACL I want to be able to define role like
guest;
writer extends guest;
editor extends writer;
grant * to writer // also grants * to editor by definition
Would that be handled better with a database than an extending object?
Suppose with my above example, a user trying to access a blog page, I also have the following tables in a database.
Code: Select all
users: id, username, groupId
groups: groupId, groupName, parentId //parentId would refer to the groupId of the parent group
resources: resourceId, resourceName
permissions: permissionId, groupId, resourceId
It wouldn't be that hard to write a little bit of code that automatically checks if any groups have the current group as a parent and then creates a new set of permissions that copies the settings to the children. Part of my goal would be to not have to write any new code once the access control system is in place, but to handle it all from an admin area.
By the way, I wasn't satisfied with calling my functions setConsumables and getConsumables, so I changed Consumables to Permissions.
Re: Simplistic Access Control
Posted: Sat Dec 13, 2008 5:29 pm
by josh
I meant the ACL class has to let you define roles that "inherit" permissions from each other. You can have multiple instances of the same role object, that just holds an instance variable of it's ancestor role... or you could check out zend / cake's ACL implementation to get a better idea.