1

I have an interceptor in which i want to do some intercepting logic based on the annotation on a controller method (Not on controller class). Say want to restrict the access to that controller method for certain users only. Is there any way to get the Handler method (Yes not the handler class) in the HandlerInterceptor?

vinothkr
  • 1,270
  • 12
  • 23

4 Answers4

3

You can do this in Spring 3.1 now with something like this:

public class ApiSecurityInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod method = (HandlerMethod) handler;
        Api methodAnnotation = method.getMethodAnnotation(Api.class);

        if (methodAnnotation != null) {
            // this method is an @Api, we check the credentials
            // you can do other things with annotation parameters at this point too
        }
    }
}

Then map it in servlet-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
...
<mvc:interceptors>
    <bean class="com.orderpipe.prototype.server.web.interceptors.ApiSecurityInterceptor"/>
</mvc:interceptors>

Then in your actual controller:

@Controller
@RequestMapping(value = "/api-service")
public class AccountApiController {

    @Api(type=CredentialType.OAUTH)
    @RequestMapping(value="get", method = RequestMethod.GET)
    public String get(Model model) {
        // secured method via oauth, for example
        // in a simpler example, you'd not have the parameter for credential type.
    }

}

I use it to implement special servlet paths that implement different security mechanisms to the normal app, for example /api uses oAuth credentials.

Ashley Schroder
  • 3,826
  • 1
  • 21
  • 16
  • thanks for the answer but, have you ever tested your Inteceptor? `java.lang.ClassCastException: com.test.web.SomeController cannot be cast to org.springframework.web.method.HandlerMethod at` `com.test.web.interceptor.SomeInterceptor.preHandle(RestSecurityInterceptor.java:29)` The handler argument in Spring 3.1 seems still a controller. – Evi Song Sep 27 '12 at 07:33
  • See the note at http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor : "When using the RequestMappingHandlerMapping the actual handler is an instance of HandlerMethod which identifies the specific controller method that will be invoked." – Ritesh Jan 31 '13 at 17:54
  • Also worth mentioning is that if you are adding interceptors using WebMvcConfigurerAdapter or WebMvcConfigurationSupport (See http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html) then handler will always be an instance of HandlerMethod. – Ritesh Jan 31 '13 at 18:15
3

I'm afraid not. You would have to group the desired methods in one (or a few) classes and base your check on the class, rather than method.

I guess you can parse the annotations yourself and match the paths, or try to see what spring does to do so in its classes, but that would be more complicated and error-prone.

You can try (but I haven't used it, so I don't know if it works) the @Interceptors annotation on your methods (saw it here)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Ya i guess you're right. We got a new requirement that needs lot of refactoring to group them :( – vinothkr May 06 '11 at 06:55
  • The blog post link uses class level annotation which is not a problem. And if i try to parse the annotation and match the paths its going to be a mess. Have to also consider the path variables, controller's url prefix. – vinothkr May 06 '11 at 07:04
  • Yes, but the annotation is also supported on a method – Bozho May 06 '11 at 07:17
1

I have the same need.

I consider an inconsistency that Spring MVC promotes the use of controller methods to handle requests, but the HandlerInterceptor interface does not supply the handler method that's going to handle the request as a parameter; only the controller object.

Requests are handled at the method level and it's the method execution what you need to intercept and for doing that efficiently you need to gain access to the method meta-information, for example, custom annotations declared at method level or its arguments.

The HandlerInterceptor.preHandle signature shoud be:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handlerInstance, Method handlerMethod) throws Exception;

So that you can do something like this:

hadlerMethod.getAnnotation(MyCustomAnnotation.class);

GOT IT?

In my case, I wanted to implement indexed-paremeter mapping; something STRIPES FRAMEWORK has (or flash scoping).

Do I have to resort to AspectJ to implement my cross-cutting functionality? DISSAPOINTING!

Agustí Sánchez
  • 10,455
  • 2
  • 34
  • 25
-1

Firstly this is against MVC architectural pattern. MVC architecture is an architectural pattern that desires to

isolate "domain logic" (the application logic for the user) from the user interface (input and presentation), permitting independent development, testing and maintenance of each (separation of concerns).

See here

And controller has a great work in it.It desires decoupling, focusing on design porpose, and etc. I hope software developers don't give up GRASP :/

Çağdaş
  • 993
  • 1
  • 12
  • 33
  • But how about cross cutting concerns like Security. Moreover the Interceptors gives you the handler object but not the handler method. I dont think it has anything to do with architectural pattern. – vinothkr May 06 '11 at 07:08
  • I didn't intent to offence you. You may do somethings always there is "a way". Previous answer is correct. But i just wanted to say something about this subject. – Çağdaş May 06 '11 at 07:11
  • Yup i didnt take that way too. But i dont find it logical really. – vinothkr May 06 '11 at 07:13