Most web applications use an authorization system to make sure the user is logged in and authorized to execute specific procedures. For example, a simple user will only have read access, while an admin can edit and delete. For every server endpoint, we ask ourselves : "Who has the privilege to access that service ?"
Implementing such a system is deceptively simple using Guice AOP once you have installed Guice Servlet to enable injection of servlet related objects, like HttpSession.
First, we need to create the annotation :
Then we implement the method interceptor :
Obviously, to get the logged in user you need the session. Thanks to Guice Servlet magic, you can inject a session provider in any object.
Finally, we bind the interceptor in the Guice ServletModule :
Don't forget that only objects instantiated by Guice will have their methods intercepted.
For such cross-cutting concerns, we are told that AOP is the key. Intercepting the methods we want to secure and checking authorization levels in a separate security aspect...
One thing that bothers me with such an approach is that when I want to check the access level of a method, I have to go look in the security aspect to see how it was intercepted. I'd rather have a declarative way to explicit the access level of a method, like an annotation :
@AuthorizationRequired(Role.ADMIN) public void securedMethod() {}
Implementing such a system is deceptively simple using Guice AOP once you have installed Guice Servlet to enable injection of servlet related objects, like HttpSession.
First, we need to create the annotation :
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AuthorizationRequired{ Role value(); }
Then we implement the method interceptor :
public class AuthorizationInterceptor implements MethodInterceptor { @Inject private Provider<HttpSession> sessionProvider; @Override public Object invoke(MethodInvocation invoc) throws Throwable { Role required = invoc.getMethod().getAnnotation(AuthorizationRequired.class).value(); User user = getUserFromSession(sessionProvider.get()); if (isUserAuthorized(user, required)) return invoc.proceed(); else throw new UnauthorizedException("User is not authorized"); } }
Obviously, to get the logged in user you need the session. Thanks to Guice Servlet magic, you can inject a session provider in any object.
Finally, we bind the interceptor in the Guice ServletModule :
AuthorizationInterceptor interceptor = new AuthorizationInterceptor (); requestInjection(interceptor); bindInterceptor(classMatcher, annotatedWith(AuthorizationRequired.class), interceptor );
Don't forget that only objects instantiated by Guice will have their methods intercepted.