Check user permission using aspect-oriented programming

In this post we will show a example of simple and clean way to check your users permissions across your application using aspect-oriented programming (AOP).

In computing, AOP is a programming paradigm which aims to increase modularity by allowing the separation of cross-cutting concerns. AOP forms a basis for aspect-oriented software development. Read more about it here.

This example is extracted from a web aplication project build on dependency injection framework Google Guice. To compliment dependency injection, Guice supports method interception that divides a problem into aspects rather than objects. This feature enables you to write code that is executed each time a matching method is invoked. It’s suited for cross cutting concerns (“aspects”), such as transactions, security and logging.

Now lets define our simple user base with this three types:

public enum UserType {
     ADMIN,
     CUSTOMER,
     GUEST;
 }

To mark select methods that need user validation, we define an annotation:

import com.google.inject.BindingAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@BindingAnnotation
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresUserType {
    UserType value();
}

…and apply it to the methods that need to be intercepted:

public class ProductService implements IProductService {

    @RequiresUserType(CUSTOMER)
    public Product view(Key key) {
        ...
    }

    @RequiresUserType(ADMIN)
    public void delete(Key key) {
        ...
    }
}

Next, we define the interceptor by implementing the org.aopalliance.intercept.MethodInterceptor interface. When we need to call through to the underlying method, we do so by calling invocation.proceed():

public class UserValidationInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        final UserType requiredType = invocation.getMethod().getAnnotation(RequiresUserType.class).value();
        //cross check current user type and throw an exception if validation fails
        ...
        //if everything checks out proceed to method execution
        return invocation.proceed();
    }
}

Finally, we configure everything. This is where we create matchers for the classes and methods to be intercepted. In this case we match any class, but only the methods with our @RequiresUserType annotation:

import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;

public class SecurityModule extends AbstractModule {
    protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.annotatedWith(RequiresUserType.class), new UserValidationInterceptor());
    }
}

The method interceptor API implemented by Guice is a part of a public specification called AOP Alliance. This makes it possible to use the same interceptors across a variety of frameworks.

About Kristijan Rebernišak

Java EE developer currently working at Five Minutes Ltd. Spends free time playing futsal, kitesurfing, snowboarding and learning new technologies.
This entry was posted in Blog, Five Minutes, Java, Technology. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>