JSR250 defines the common annotations for Java. Included in these are the javax.annotation.security.* annotations, including @RolesAllowed, @DenyAll, and @PermitAll; they can be used in EJBs to protect service calls.
I’m currently using Spring Portlet MVC 2.5, which supports an annotation-driven style of development. This means that you don’t need to implement framework-specific classes to build a portlet controller and that the methods in your controller can have flexible names and signatures. Unfortunately, as of V2.5, the Spring framework doesn’t support the JSR250 security annotations on Portlet (or Web) controllers.
In this article, I’ll describe how I enabled support for the JSR250 security annotations on these custom, flexible Spring Portlet MVC controller methods.
Option 1: Spring Security
I read a bit about Spring Security (formerly Acegi) off the bat, which would (in the latest versions) support the @RolesAllowed and other annotations. I decided against Spring Security, however, primarily because it seems like overkill in the Portal environment. Most Portal platforms provide various services for authentication and authorization, so a lot of what Spring Security provides is unnecessary.
Option 2: Add an Interceptor to DefaultAnnotationHandlerMapping
When using the DefaultAnnotationHandlerMapping strategy, Spring Portlet MVC handles a Portlet request in two steps: 1) determine the appropriate handler class (typically annotated with @Controller) then 2) determine the appropriate method on the handler class to handle the method call. The org.springframework.web.portlet.handler.HandlerInterceptorAdapter class intercepts calls into the handler class *before* the method is determined - so option 2 is no option at all.
Option 3: Extend AnnotationMethodHandlerAdapter
See: http://jira.springframework.org/browse/SPR-4525. This solution would involve overriding the org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter, the class that handles step 2 of the portlet request process described above, to add support for checking the javax.security annotations. I decided against this approach because the extension would be a bit messy, as the actual method resolving logic is hidden in a private nested static class, and several of the other crucial methods are private. In short, I think there is more risk with this approach than my final option (which I decided to use).
Solution: Option 4: Use AOP to Intercept the HandlerMethodResolver Calls
In my scenario, we were already utilizing AspectJ for AOP in our Portal environment, so I decided to write an aspect to intercept calls to the method resolving logic. This route seemed less risky and more modular than extending the AnnotationMethodHandlerAdapter class. In short, this aspect will be applied after step 2 (the handler method is determined) to inspect the chosen method for the appropriate annotations.
So, check out SpringJSR250SecurityAspect.
- Currently the solution I have put together only works in the portlet environment. It should be fairly easy to extend the aspect to support annotated controllers in the web environment (Spring Web MVC) or even GenericPortlets.
- Section 2.11 of the JSR250 spec describes how applications should work when multiple annotations are applied on a given class and its methods - currently the solution I provided only works for annotations at the method level.