Announcement Announcement Module
No announcement yet.
Dynamic Links Based on Definitions in AppContext file Page Title Module
Move Remove Collapse
This topic is closed
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamic Links Based on Definitions in AppContext file

    I would like to display links based on whether the user has permission to view the URL as defined in my AppContext file. I have already defined in my ApplicationContext the URLs and the roles that are permitted to see them in the objectDefinitionSource of the FilterSecurityInterceptor. I don't want to use the current Ageci taglibs because I have already defined if the user can go to that URL in the context file and want to keep this centralized.

    So basically I was wondering how I could write a tag which would do this:

    1. Take in a URL
    2. Get the GrantedAuthorities from the Authentication obj
    3. Lookup the URL in the objectDefinitionSource and get it's valid roles
    4. Compare the GrantedAuthorities to the URL's valid roles

    How do I get the objectDefinitionSource in my custom tag and consequently the ConfigAttributes?



  • #2
    Could you use WebApplicationContextUtils.getRequiredWebApplicati onContext to obtain the executing application context and then the objectDefinitionSource bean?


    • #3

      Once I get the ObjectDefinitionSource, how do I query it to get the correct URL's attributes?

      Here is what I have so far (my tag extends RequestContextAwareTag):

      String resolvedURL = ExpressionEvaluationUtils.evaluateString("url", this.url, pageContext);
      Map beans = this.getRequestContext().getWebApplicationContext().getBeansOfType(FilterSecurityInterceptor.class);
      //Get the 1 FSI definition
      FilterSecurityInterceptor fsi = (FilterSecurityInterceptor) beans.values().iterator().next();
      //How do I do this??
      ConfigAttributeDefinition attr = fsi.obtainObjectDefinitionSource().getAttributes(Need FilterInvocation obj????)
      if (attr != null) {
                  Authentication auth = ((SecureContext) ContextHolder.getContext())
                  try {
                      fsi.getAccessDecisionManager().decide(auth, resolvedURL, attr);
                  } catch (AccessDeniedException e) {
                      return SKIP_BODY;
              return EVAL_BODY_INCLUDE;


      • #4
        Once you get the FilterSecurityInterceptor from the application context, use filterSecurityInterceptor.getObjectDefinitionSourc e(). This will return a FilterInvocationDefinitionSource, which is usually RegExpBasedFilterInvocationDefinitionMap or PathBasedFilterInvocationDefinitionMap depending on what the FilterInvocationDefinitionSourceEditor property editor setup when wiring the bean.

        The XXXFilterInvocationDefinitionMap has a getAttributes(Object) method, which delegates to lookupAttributes(FilterInvocation filterInvocation). You'll need to use this method. You will need to create a FilterInvocation containing the URL you are requesting configuration attributes for. Specifically, the XXXFilterInvocationDefinitionMap will call filterInvocation.getRequestUrl() to determine the URL, so ensure that you provide a mock ServletRequest that can provide the properties used in the FilterInvocation.getRequestUrl() method. The other mock objects needed by FilterInvocation (ie ServletResponse and FilterChain) can safely throw UnsupportedOperationException for all of their methods, as your XXXFilterInvocationDefinitionMap does not use them.

        Don't forget an ObjectDefinitionSource (which includes XXXFilterInvocationDefinitionMap) can return null from its getAttributes(Object) method if it cannot find configuration attributes for the secure object. So expect to handle this in your code.


        • #5

          Got it to work, though it's kind of a hack since I had to create a DummyFilterChain object. But, nevertheless it works!

          Thanks again....



          • #6
            I recent refactored out the MethodInvocation-related ObjectDefinitionSources to work with a java.lang.reflect.Method rather than MethodInvocation.

            We could do the same with the FilterInvocation-related objects. Instead of pass around a FilterInvocation, just pass a new object containing the getRequestUrl(). This would make implementations a lot cleaner, at risk of not exposing some HttpServletRequest property people may wish to consider in their ObjectDefinitionSource that is not already part of getRequestUrl(). Such people could always implement their own ObjectDefinitionSource that works with the FilterInvocation itself, like we presently do.

            As someone actually using this area of the code, how would you feel about this proposed refactoring? I personally think it would tidy things up and make it easier to implement the more common usage case you're addressing.


            • #7
              I agree, I think it would definitely tidy things up and make it more generalized. It makes a lot more sense for me to just create an object with the getRequestUrl() method instead of creating an entire dummy FilterChain object just so I can create a FilterInvocation object so I can get at the ConfigAttributes.

              Very cool!



              • #8
                I've just added to CVS the above refactoring. Views can now access the config attributes defined against FilterSecurityInterceptor simply via a String representation of the web request URL pattern.


                • #9
                  Awesome! Thanks.


                  • #10
                    How do you create a dummy Filter Chain?


                    • #11
                      Originally posted by snb27
                      How do you create a dummy Filter Chain?
                      You don't need to. Just use AbstractFilterInvocationDefinitionSource.lookupAtt ributes(String url).