Announcement Announcement Module
Collapse
No announcement yet.
Creating a controller level annotation that will check request attributes for objects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Creating a controller level annotation that will check request attributes for objects

    Is it possible to create a controller level annotation that will check if there are specific objects in the request Attributes collection?

    If not, I want to redirect to the signin page.

    I currently have code in each and every controller method, and this isn't the best way since a developer can forget to have this security type checks in the method and it can open a security hole.

    Having something at the controller annotation level would be much easier.

  • #2
    That is what HandlerInterceptors are for. You can check that in the preHandle method.

    Comment


    • #3
      Marten,

      Yes that is what I am currently doing, but not in a programatic way per say.

      Currently I am looking at the url, for example, if my controller is ProductController like:

      Code:
      @RequestMapping("/products")
      @Controller
      public class ProductController ... {
      
      }
      And then in my interceptor am doing:

      Code:
      String url = request.getRequestURI().toLowerCase();
      
      if(url.contains("products/")) {
        loginRequired = true;
      }
      Now this might work, it doesn't seem like a clean solution to me because it is doing string based comparison's on the url and a developer might introduce a security hole somehow.

      Is there a way to actually know which controller is going to be used to service this request at this point?

      Or in your opinion, what I am doing now is pretty much all I can do?

      Comment


      • #4
        If it is security you want I suggest Spring Security instead of inventing your own.

        What you can do depends a little on which version of Spring you are on. You could create an annotation (@Secured or something) and check in the interceptor if the annotation is present on the class if so login. That at least saves you all the checks for the URL. The controller is available as a method argument, for Spring 3.1 this will be a HandlerMethod instead of the actual class so you need to do some additional work to get to the actual class.

        Originally posted by SpringOrSummer
        Is it possible to create a controller level annotation that will check if there are specific objects in the request Attributes collection?
        It is only useful to create a generic part if it concerns general objects if they differ per controller this isn't going to work.

        Comment


        • #5
          Ok I am getting access to the handlermethod (thanks for that link!), but having an issue with the annotation, it is always null for some reason.

          First time created an annotation so that might be the issue

          Code:
          public @interface SomeThing {
          }
          Controller:

          Code:
          @SomeThing
          @RequestMapping("/products")
          @Controller
          public class ProductController {
          
             @SomeThing
              @RequestMapping("/")
              public ModelAndView index(HttpServletRequest request, HttpServletResponse response) {
               ...
              }
          
          }
          I added the annotation on both the class and method level just for testing, now in my interceptor:

          Code:
                 HandlerMethod method = (HandlerMethod) handler;
                  SomeThing annotation1 = method.getMethodAnnotation(SomeThing.class);
          
                  SomeThing annotation2 = method.getMethod().getAnnotation(SomeThing.class);
          Both values are null when I am in the ProductController.

          What am I doing wrong?

          Comment


          • #6
            The annotation isn't on the method but on the bean... (Edit: Missed that it is actually on the method ).

            The first and second are the same (what you do is more or less the same that happens internally).

            Code:
            HandlerMethod method = (HandlerMethod) handler;
            Object bean = method.getBean();
            SomeThing annot= AnnotationUtils.findAnnotation(bean.getClass(), SomeThing.class);
            if (annot != null) {
              //apply security
            }
            The above should be more or less what you want.

            Edit: Can you post the full annotation code? Make sure it is available at runtime.

            Code:
            @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
            @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
            public @interface SomeThing {
            }
            Something like this (from the top of my head).

            Comment


            • #7
              Marten,

              Thanks that worked, I actually didn't have any annotations on my annotation! (and it wasn't working)

              I just added the Retention and Target and now it works.

              I'm guessing TYPE is at the class level, and METHOD is at the method level.

              How do you know this stuff man?? thanks! lol

              Comment


              • #8
                Originally posted by SpringOrSummer
                How do you know this stuff man?? thanks! lol
                A lot of reading and making even more mistakes (and learn from them) in an era that forums wheren't that helpful or available.

                Comment


                • #9
                  Marten,

                  So when I add the same annotation on a controller method, it doesn't seem to work i.e. authenticationRequiredAnnotation == null (see below)

                  Any ideas why this may be?

                  Code:
                  @Retention(RetentionPolicy.RUNTIME)
                  @Target({ElementType.TYPE, ElementType.METHOD})
                  public @interface AuthenticationRequired {
                  }
                  
                  
                  // in my interceptor I am doing
                  
                  HandlerMethod method = (HandlerMethod) handler;
                  
                              if (method != null) {
                                  Object bean = method.getBean();
                                  if (bean != null) {
                                      AuthenticationRequired authenticationRequiredAnnotation = AnnotationUtils.findAnnotation(bean.getClass(), AuthenticationRequired.class);
                                      if (authenticationRequiredAnnotation != null) {
                                          requiresAuthentication = true;
                                      }
                                  }
                              }

                  Comment


                  • #10
                    You are using the wrong method... You want to pass in the method not the class to the findAnnotation as that will check the method, the method you are now calling is checking for classlevel annotations only.

                    Code:
                    if (handler != null) {
                    	Method method = ((HandlerMethod) handler).getMethod();
                    	if (method != null) {
                    		AuthenticationRequired authenticationRequiredAnnotation = AnnotationUtils.findAnnotation(method, AuthenticationRequired.class);
                    		if (authenticationRequiredAnnotation != null) {
                    			requiresAuthentication = true;
                    		}
                    	}
                    }
                    Something like the above, which should work for either case.
                    Last edited by Marten Deinum; Oct 11th, 2012, 02:17 AM.

                    Comment


                    • #11
                      Now that worked for the method level, but failed when I added the annotation at the controller level.

                      My code:

                      Code:
                                  HandlerMethod handlerMethod = (HandlerMethod) handler;
                      
                                  if (handlerMethod != null) {
                                      //Object bean = handlerMethod.getBean();
                                      Method method = handlerMethod.getMethod();
                                      if (method != null) {
                                          AuthenticationRequired authenticationRequiredAnnotation = AnnotationUtils.findAnnotation(method, AuthenticationRequired.class);
                                          if (authenticationRequiredAnnotation != null) {
                                              requiresAuthentication = true;
                                          }
                                      }
                                  }

                      Comment


                      • #12
                        My bad... I was under the impression that that method also scanned class level but as it turnsout it scans interfaces. So you need to do both I'm afraid. First check the method, if annotation still null check the class (your initial findAnnotation call) ...

                        Comment


                        • #13
                          It seems that this will work of this annotation codes and I am happy that you have given this thread to us. I will try this to see if my source will work.

                          Comment

                          Working...
                          X