CakePHP - restricting editing to your own "data"
At the moment I use Auth Component for users to login / logout - ACL is defined to sort between user groups (Guests, Users, Admins) - with obvious restrictions; Admin being able to access everything, the user can only access edit in the users controller and the guest being able to see just the display / index / view etc etc.
Now to prevent users from editing another user - I have a function called isOw开发者_运维技巧ner() which essentially checks if you are trying to edit your own profile; and also checks if it is an admin trying to edit. If the user is the owner of the content they're trying to edit, then it allows it otherwise it just redirects with a flash message.
Having read through http://book.cakephp.org/view/1245/Defining-Permissions-Cake-s-Database-ACL - I wondered if it was possible to define this in the ACL?
Something along the lines of:
$this->Acl->allow(array('model' => 'User', 'foreign_key' => $id), 'Users', 'edit', $id)
Though I haven't dug deep enough and I'm assuming I'd have to make some sort of beforeSave() with the above line for each new user registered to be allowed to edit his profile.
[ i've decided to post this as an answer cause it contains code examples ]
You could create a component (or a function) and use the beforeFilter() callback in the app_controller, that way you wont need to manually add the function to all controllers.
Also you could use multiple prefixes for the actions (see Routing.prefixes
in the core), it will make it easier to control the access. Something like:
[app_controller.php]
function beforeFilter() {
if(isset($this->params['prefix']) && $this->params['prefix'] == 'admin'){
if(!isAdmin() || !isOwner())
$this->cakeError('error404');
}
}
[users_controller.php]
function admin_edit($id = null){
... // edit as usual
}
In a LAMP stack your bottleneck is usually at the database
my problem with cake is the number of queries it makes. Once i saw that my "contact" page that made 21 queries only to retrieve the data structure, and the permissions for this public page.
The only way to justify the use of ACL for accessing data is when the permissions are dynamic, i.e. "user#29 can edit user#12 because the Admin decided it in the backoffice". But if you have static rules for accessing the data (like "users can only edit their own info and admins can edit everything") its kinda useless to perform queries when you already know the answers, because this rules won't change in time.
so it all depends on your app.. Finally, one last thought, if you're still planing to make more queries =P you could set the authorize method of the Auth component. But using the ACL Component for this, seems to me like a bad idea
Cheers!
Ok it's almost 4 years later but for those who like me stumble across this researching an Acl solution for a CakePHP app; The short answer is yes it is possible, but it has to be planned carefully. If you really need this level of Auth there is not really a viable alternative to Cake's ACL implementation, which is at the least sound (not going into a critique...). Note current stable version is 2.4:
In essence, the solution is to replace your isOwner()
call in your code with $dbAcl->check($user, $entity, $action);
which does a lookup on your ACL db structure - see http://api.cakephp.org/2.4/class-DbAcl.html.
There is more to it than that of course. CakePHP does not provide you with an out of the box solution for this type of authentication at the entity level. It provides you a toolkit that you can use to build one:
- The DbAcl for querying the ACL db structure.
- The AclBehavior. The models of the classes of objects that you want to apply entity level authorization on should load the Acl behavior. This automatically creates and deletes object level ACO/AROs, taking care of everything there. See http://api.cakephp.org/2.4/class-AclBehavior.html.
- Controller level authorization with Controller::isAuthorized(). This is where you'll call
dbAcl::check()
. See http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#authorization. You could also do it from a custom Authorize module if you really wanted. - You still need to complement this by using either CRUD or Action Authorize component. Its important to realize that in a default CakePHP baked controller there are 2 implicit subclasses of action/endpoint. Those that act on the Controller itself (add,index) and those that act on an entity of the class of objects represented by the controller (edit,view,delete). This is analogous to class vs instance methods. The type of authorization described is only applicable to the end point that acts on an entity. You fallback to Action/Crud auth for the rest.
- You'll obviously need a User model..
Note there is two good tutorials at the end of the Cake docs on ACL - http://book.cakephp.org/2.0/en/tutorials-and-examples. They don't cover this type of setup explicitly but given an understanding of the concepts covered plus dBAcl
you should be able to make you own way.
精彩评论