I am using Spring Security ACL. When I save an object I also create a new ACE (Access Control Entry). I am using this method:
acl.insertAce(acl.getEntries().size(), BasePermission.CREATE, recipient, true);
I am wondering if I got it right when I invoke this method one time for all the permission the owner (the authenticated user that added it) should have and the same for authorities?
Example:
If the user who adds the entry also should have READ access I invoke this one more time:
acl.insertAce(acl.getEntries().size(), BasePermission.READ, recipient, true);
And so on? This is the way it is supposed to be used right?
And is it normal to have both the authorities and the principals in ACL or just the principals. I mean, do you mix hasRole('ROLE_ADMIN')
and hasPermission(...)
in the @PreAuthorize
or do you have both principals and authorities in ACL so you only use hasPermission(...)
By default, when Spring Security ACL evaluates permissions it will take into account higher permissions. For example, if you have CREATE (2) permission, that automatically means you have READ (1) permission. For some reason I am having a hard time locating that particular query, it's in one of their default strategy impls. So, you shouldn't have to grant READ rights after CREATE rights have been given.
As far as combining role and permission checking, perfectly normal to do. For example, in my application system admins (ROLE_ADMIN) are super users who can do anything, e.g. update other user's data, so here is how I check if the current user can update an entity, where #entity is the actual object you are updating:
@PreAuthorize("hasPermission(#entity, 'ADMINISTRATION') or hasRole('ROLE_ADMIN')")
If you want finer grained permissions, you can use security groups. For example, in my application users advertise different classes they teach, classes can be taught at global level (user@example.com can teach this class anywhere), at gym level (any trainer at gym ID 123 can teach this class) or at gym-trainer level (user@example.com can teach this class at gym ID 123). In order to support something like that, you'd need to have 3 levels of permissions:
Global: user@example.com -> this is a SidPrincipal
Gym: GYM_123_TRAINERS -> this is a GrantedAuthoritySid
Gym-trainer: GYM_123_TRAINERS-user@example.com -> this is a GrantedAuthoritySid
When user logs in, I loop over all the gyms he teaches at and add GYM_ID_TRAINERS role to identify him as being part of the gym trainer group, and GYM_ID_TRAINERS-username role to identify him as him at that gym.