With Spring and a bunch of AOP I’ll show how it’s easy to add protectionsof your business components and notify the view that the user is not authorizedto perform a specific action.This example relies on Spring 2.0 and Spring MVC for the presentation layer.Let’s take an example of a service that executes jobs whose class is named JobExecutorService.This service has methods to add jobs in a Job queue, remove a job from the queueor stop a running job. We would like to authorize only owners of a job to remove the job or stop it. The jobs are persistent (to recover from failure).
1) Defining the authorization aspectLet’s define in Spring’s application context a Job authorization advice and inject it a Job DAO to access persistent jobs.
1 2 3 4 5 | |
Here’s below the simplified code of the bean advice which is just a POJOwhich benefits from injection.When the user doesn’t own the Job an AuthorizationException is thrown.We’ll see later how to deal with the exception.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
I used Spring to bind user’s context (which stores user information) to the current Thread via a ThreadLocal to easily retrieve user’s data stored in memory and avoid being tied to the Servlet API. ContextMgr classhas a static method to retrieve user’s context.Actually binding is done with a Spring MVC interceptor on controllers in the Spring Web Application Context(you could also use a Servlet filter):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
The ContextInterceptor bean just retrieves user’s data from the HTTP session and binds it to the current thread
2) Declaring the poincutsThen we add pointcuts to execute the aspect. Here the pointcuts are defined with AspectJ expressions
1 2 3 4 5 6 7 8 | |
So here we are weaving our jobAuthorizationAspect advice with the JobExecutorService bean (not detailed here).The proxyTargetClass attribute is here because the JobExecutorService is declared elsewehere in Spring’s applicationContext and injected and used directly in Spring MVC controllers not via its interfaces. But the bean’s class implements multiple interfaces (infrastructure interfaces like Observer )Spring’s default behaviour is when it detects that the class implements interfaces it to use Java dynamic proxies. So here we set this attribute to force CGLib proxying.The arg-names attribute is here to be as explicit as possible and make sure that our “before” advice is executed for the proper methods of JobExecutorService and that the Job argument is passed (by reference) to the “checkForAuthorization” method of our advice.
3) Dealing with the AuthorizationExceptionSpring has a mechanism that allows to intercept exceptions and deal with them.We could catch the error and redirects to a page displaying a generic authorization message,we’ll choose to extend this concept to return to the submitting view to display the message.Here’s the declaration of the AuthorizedExceptionResolver
1 2 3 | |
And a simplified version of the code (we’ll suppose that all our controllersare SimpleFormController ). :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
Here I made the assumption that the command (object that maps the HTTP submitted parameters)has been bound to user’s session in the controller (Spring has mechanism to do this)and that the form’s view first check that if the form’s command is in the user’s sessionit uses it to populate the form’s fields.We’ll also suppose that the controller’s form view has a box that displays messages whenfound in the request context under the messages attribute (like flash boxes of ROR).
Conclusion:AOP is the perfect tool to protect business components in a non-intrusive way.Thanks to Spring MVC framework techniques we can create a very flexible and genericway to handle authorizations and report authorization exceptions in our web layer. (using many of the Java EE cool buzz technos)
N.B: Sorry for my poor English…