/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.security.config.method; import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.access.SecurityConfig; import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor; import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource; import org.springframework.security.config.BeanIds; import org.springframework.security.config.Elements; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.util.*; /** * @author Luke Taylor * @author Ben Alex * */ public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator { private final BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator(); public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { MethodConfigUtils.registerDefaultMethodAccessManagerIfNecessary(parserContext); return delegate.decorate(node, definition, parserContext); } } /** * This is the real class which does the work. We need access to the ParserContext in * order to do bean registration. */ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { static final String ATT_METHOD = "method"; static final String ATT_ACCESS = "access"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; protected BeanDefinition createInterceptorDefinition(Node node) { Element interceptMethodsElt = (Element) node; BeanDefinitionBuilder interceptor = BeanDefinitionBuilder .rootBeanDefinition(MethodSecurityInterceptor.class); // Default to autowiring to pick up after invocation mgr interceptor.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR); if (!StringUtils.hasText(accessManagerId)) { accessManagerId = BeanIds.METHOD_ACCESS_MANAGER; } interceptor.addPropertyValue("accessDecisionManager", new RuntimeBeanReference( accessManagerId)); interceptor.addPropertyValue("authenticationManager", new RuntimeBeanReference( BeanIds.AUTHENTICATION_MANAGER)); // Lookup parent bean information String parentBeanClass = ((Element) node.getParentNode()).getAttribute("class"); // Parse the included methods List<Element> methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); Map<String, BeanDefinition> mappings = new ManagedMap<String, BeanDefinition>(); for (Element protectmethodElt : methods) { BeanDefinitionBuilder attributeBuilder = BeanDefinitionBuilder .rootBeanDefinition(SecurityConfig.class); attributeBuilder.setFactoryMethod("createListFromCommaDelimitedString"); attributeBuilder.addConstructorArgValue(protectmethodElt .getAttribute(ATT_ACCESS)); // Support inference of class names String methodName = protectmethodElt.getAttribute(ATT_METHOD); if (methodName.lastIndexOf(".") == -1) { if (parentBeanClass != null && !"".equals(parentBeanClass)) { methodName = parentBeanClass + "." + methodName; } } mappings.put(methodName, attributeBuilder.getBeanDefinition()); } BeanDefinition metadataSource = new RootBeanDefinition( MapBasedMethodSecurityMetadataSource.class); metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); interceptor.addPropertyValue("securityMetadataSource", metadataSource); return interceptor.getBeanDefinition(); } }