View Javadoc
1   package org.springframework.security.oauth.config;
2   
3   import java.lang.reflect.Method;
4   import java.util.Collections;
5   import java.util.List;
6   
7   import org.springframework.beans.BeanMetadataElement;
8   import org.springframework.beans.factory.config.BeanDefinition;
9   import org.springframework.beans.factory.config.BeanReference;
10  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
11  import org.springframework.beans.factory.support.ManagedMap;
12  import org.springframework.beans.factory.xml.ParserContext;
13  import org.springframework.security.access.SecurityConfig;
14  import org.springframework.security.config.BeanIds;
15  import org.springframework.security.config.http.MatcherType;
16  import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
17  import org.springframework.util.ReflectionUtils;
18  import org.springframework.util.StringUtils;
19  import org.springframework.util.xml.DomUtils;
20  import org.w3c.dom.Element;
21  
22  
23  /**
24   * Common place for OAuth namespace configuration utils.
25   *
26   * @author Ryan Heaton
27   */
28  public class ConfigUtils {
29    private static final Method createMatcherMethod3x = ReflectionUtils.findMethod(
30            MatcherType.class, "createMatcher", String.class, String.class);
31    private static final Method createMatcherMethod4x = ReflectionUtils.findMethod(
32            MatcherType.class, "createMatcher", ParserContext.class, String.class, String.class);
33  
34    private ConfigUtils() {
35    }
36  
37    public static BeanDefinition createSecurityMetadataSource(Element element, ParserContext pc) {
38      List<Element> filterPatterns = DomUtils.getChildElementsByTagName(element, "url");
39  
40      if (filterPatterns.isEmpty()) {
41        return null;
42      }
43  
44      String patternType = element.getAttribute("path-type");
45      if (!StringUtils.hasText(patternType)) {
46        patternType = "ant";
47      }
48  
49      MatcherType matcherType = MatcherType.valueOf(patternType);
50  
51      ManagedMap<BeanDefinition, BeanDefinition> invocationDefinitionMap = new ManagedMap<BeanDefinition, BeanDefinition>();
52  
53      for (Element filterPattern : filterPatterns) {
54        String path = filterPattern.getAttribute("pattern");
55        if (!StringUtils.hasText(path)) {
56          pc.getReaderContext().error("pattern attribute cannot be empty or null", filterPattern);
57        }
58  
59        String method = filterPattern.getAttribute("httpMethod");
60        if (!StringUtils.hasText(method)) {
61          method = null;
62        }
63  
64        String access = filterPattern.getAttribute("resources");
65  
66        if (StringUtils.hasText(access)) {
67          BeanDefinition matcher;
68          if (createMatcherMethod4x != null) {
69            matcher  = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod4x, matcherType, pc, path, method);
70          } else {
71            matcher  = (BeanDefinition)ReflectionUtils.invokeMethod(createMatcherMethod3x, matcherType, path, method);
72          }
73  
74          if (access.equals("none")) {
75            invocationDefinitionMap.put(matcher, BeanDefinitionBuilder.rootBeanDefinition(Collections.class).setFactoryMethod("emptyList").getBeanDefinition());
76          }
77          else {
78            BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder.rootBeanDefinition(SecurityConfig.class);
79            attributeBuilder.addConstructorArgValue(access);
80            attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString");
81  
82            if (invocationDefinitionMap.containsKey(matcher)) {
83              pc.getReaderContext().warning("Duplicate URL defined: " + path
84                                              + ". The original attribute values will be overwritten", pc.extractSource(filterPattern));
85            }
86  
87            invocationDefinitionMap.put(matcher, attributeBuilder.getBeanDefinition());
88          }
89        }
90      }
91  
92      BeanDefinitionBuilder fidsBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultFilterInvocationSecurityMetadataSource.class);
93      fidsBuilder.addConstructorArgValue(invocationDefinitionMap);
94      fidsBuilder.getRawBeanDefinition().setSource(pc.extractSource(element));
95  
96      return fidsBuilder.getBeanDefinition();
97    }
98  
99    @SuppressWarnings({"unchecked"})
100   public static List<BeanMetadataElement> findFilterChain(ParserContext parserContext, String explicitRef) {
101     String filterChainRef = explicitRef;
102     if (!StringUtils.hasText(filterChainRef)) {
103       filterChainRef = findDefaultFilterChainBeanId(parserContext);
104     }
105     return (List<BeanMetadataElement>)
106             parserContext.getRegistry().getBeanDefinition(filterChainRef).getConstructorArgumentValues().getArgumentValue(1,List.class).getValue();
107   }
108 
109   @SuppressWarnings({"unchecked"})
110   protected static String findDefaultFilterChainBeanId(ParserContext parserContext) {
111     BeanDefinition filterChainList = parserContext.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
112     // Get the list of SecurityFilterChain beans
113     List<BeanReference> filterChains = (List<BeanReference>)
114               filterChainList.getPropertyValues().getPropertyValue("sourceList").getValue();
115 
116     return filterChains.get(filterChains.size() - 1).getBeanName();
117   }
118 
119 }