spring-security how ACL grants permissions

Pete picture Pete · Sep 20, 2011 · Viewed 13.3k times · Source

I'm currently integrating springs-security into our new web application stack. We will need to be able to grant permissions for a user or role to access a specific object or all objects of a certain type. However that's one thing I didn't really get when working through documentations and examples:

Does an ACL only grant permissions to a user/role for a single object or does it do that for the entire type? As I understand it, domain object means the type but the examples and tutorials seem like they assign permissions to specific objects. Am I just confused or can I do both? If not, how do I do the other?

Thanks!

Answer

Vladimir Tsvetkov picture Vladimir Tsvetkov · Sep 20, 2011

With spring-security you can do both. It's possible because spring-security supports the so called permission rules - within the spring-security terminology they call it permission evaluators. Permission rules encompass ACL, but also you can secure instances of objects when they're in a certain state...etc.

This is how it works:

  1. You need to extend the PermissionEvaluator - this allows you to have super custom logic for determining access rights - you can check the type of the object or check for a particular id, or check if the user invoking the method is the user that created the object, etc.:

    public class SomePermissionsEvaluator implements PermissionEvaluator {
        @Override
        public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
            if (permission.equals("do_something") && 
            /*authentication authorities has the role A*/) {
                return true
            } else if (permission.equals("do_something_else") && 
            /*authentication authorities has the role B*/) {
                return /*true if targetDomainObject satisfies certain condition*/;
            }
    
            return false;
        }
    
        @Override
        public boolean hasPermission(Authentication authentication,
            Serializable targetId, String targetType, Object permission) {
        throw new UnsupportedOperationException();
        }
    }
    
  2. Now that you have a security rule, you need to apply it through annotations:

    @PreAuthorize("hasRole('SOME_ROLE_OR_RIGHT') and" +
    " hasPermission(#someDomainObject, 'do_something')")
    public void updateSomeDomainObject(SomeDomainObject someDomainObject) {
        // before updating the object spring-security will check the security rules
    }
    
  3. In order for this to work the security annotations should be enabled in the applicationContext.xml:

    <global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
        <expression-handler ref="expressionHandler"/>
    </global-method-security>
    
    <beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <beans:property name="permissionEvaluator">
            <beans:bean id="permissionEvaluator" class="com.npacemo.permissions.SomePermissionsEvaluator"/>
        </beans:property>
    </beans:bean>