spring security GlobalMethodSecurityBeanDefinitionParser 源码

  • 2022-08-13
  • 浏览 (428)

spring security GlobalMethodSecurityBeanDefinitionParser 代码

文件路径:/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java

/*
 * Copyright 2002-2018 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
 *
 *      https://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 java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;

import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.target.LazyInitTargetSource;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.log.LogMessage;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource;
import org.springframework.security.access.annotation.Jsr250Voter;
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.ExpressionBasedAnnotationAttributeFactory;
import org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice;
import org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.intercept.AfterInvocationProviderManager;
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter;
import org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.Elements;
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;

/**
 * Processes the top-level "global-method-security" element.
 *
 * @author Ben Alex
 * @author Luke Taylor
 * @author Rob Winch
 * @since 2.0
 */
public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser {

	private final Log logger = LogFactory.getLog(getClass());

	private static final String ATT_AUTHENTICATION_MANAGER_REF = "authentication-manager-ref";

	private static final String ATT_ACCESS = "access";

	private static final String ATT_EXPRESSION = "expression";

	private static final String ATT_ACCESS_MGR = "access-decision-manager-ref";

	private static final String ATT_RUN_AS_MGR = "run-as-manager-ref";

	private static final String ATT_USE_JSR250 = "jsr250-annotations";

	private static final String ATT_USE_SECURED = "secured-annotations";

	private static final String ATT_USE_PREPOST = "pre-post-annotations";

	private static final String ATT_REF = "ref";

	private static final String ATT_MODE = "mode";

	private static final String ATT_ADVICE_ORDER = "order";

	private static final String ATT_META_DATA_SOURCE_REF = "metadata-source-ref";

	@Override
	public BeanDefinition parse(Element element, ParserContext pc) {
		CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
				pc.extractSource(element));
		pc.pushContainingComponent(compositeDef);
		Object source = pc.extractSource(element);
		// The list of method metadata delegates
		ManagedList<BeanMetadataElement> delegates = new ManagedList<>();
		boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
		boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
		boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
		boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE));
		BeanDefinition preInvocationVoter = null;
		ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<>();
		// Check for an external SecurityMetadataSource, which takes priority over other
		// sources
		String metaDataSourceId = element.getAttribute(ATT_META_DATA_SOURCE_REF);
		if (StringUtils.hasText(metaDataSourceId)) {
			delegates.add(new RuntimeBeanReference(metaDataSourceId));
		}
		if (prePostAnnotationsEnabled) {
			Element prePostElt = DomUtils.getChildElementByTagName(element, Elements.INVOCATION_HANDLING);
			Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER);
			if (prePostElt != null && expressionHandlerElt != null) {
				pc.getReaderContext().error(Elements.INVOCATION_HANDLING + " and " + Elements.EXPRESSION_HANDLER
						+ " cannot be used together ", source);
			}
			BeanDefinitionBuilder preInvocationVoterBldr = BeanDefinitionBuilder
					.rootBeanDefinition(PreInvocationAuthorizationAdviceVoter.class);
			// After-invocation provider to handle post-invocation filtering and
			// authorization expression annotations.
			BeanDefinitionBuilder afterInvocationBldr = BeanDefinitionBuilder
					.rootBeanDefinition(PostInvocationAdviceProvider.class);
			// The metadata source for the security interceptor
			BeanDefinitionBuilder mds = BeanDefinitionBuilder
					.rootBeanDefinition(PrePostAnnotationSecurityMetadataSource.class);
			if (prePostElt != null) {
				// Customized override of expression handling system
				String attributeFactoryRef = DomUtils
						.getChildElementByTagName(prePostElt, Elements.INVOCATION_ATTRIBUTE_FACTORY)
						.getAttribute("ref");
				String preAdviceRef = DomUtils.getChildElementByTagName(prePostElt, Elements.PRE_INVOCATION_ADVICE)
						.getAttribute("ref");
				String postAdviceRef = DomUtils.getChildElementByTagName(prePostElt, Elements.POST_INVOCATION_ADVICE)
						.getAttribute("ref");
				mds.addConstructorArgReference(attributeFactoryRef);
				preInvocationVoterBldr.addConstructorArgReference(preAdviceRef);
				afterInvocationBldr.addConstructorArgReference(postAdviceRef);
			}
			else {
				// The default expression-based system
				String expressionHandlerRef = (expressionHandlerElt != null) ? expressionHandlerElt.getAttribute("ref")
						: null;
				if (StringUtils.hasText(expressionHandlerRef)) {
					this.logger.info(LogMessage.format("Using bean '%s' as method ExpressionHandler implementation",
							expressionHandlerRef));
					RootBeanDefinition lazyInitPP = new RootBeanDefinition(
							LazyInitBeanDefinitionRegistryPostProcessor.class);
					lazyInitPP.getConstructorArgumentValues().addGenericArgumentValue(expressionHandlerRef);
					pc.getReaderContext().registerWithGeneratedName(lazyInitPP);
					BeanDefinitionBuilder lazyMethodSecurityExpressionHandlerBldr = BeanDefinitionBuilder
							.rootBeanDefinition(LazyInitTargetSource.class);
					lazyMethodSecurityExpressionHandlerBldr.addPropertyValue("targetBeanName", expressionHandlerRef);
					BeanDefinitionBuilder expressionHandlerProxyBldr = BeanDefinitionBuilder
							.rootBeanDefinition(ProxyFactoryBean.class);
					expressionHandlerProxyBldr.addPropertyValue("targetSource",
							lazyMethodSecurityExpressionHandlerBldr.getBeanDefinition());
					expressionHandlerProxyBldr.addPropertyValue("proxyInterfaces",
							MethodSecurityExpressionHandler.class);
					expressionHandlerRef = pc.getReaderContext()
							.generateBeanName(expressionHandlerProxyBldr.getBeanDefinition());
					pc.registerBeanComponent(new BeanComponentDefinition(expressionHandlerProxyBldr.getBeanDefinition(),
							expressionHandlerRef));
				}
				else {
					RootBeanDefinition expressionHandler = registerWithDefaultRolePrefix(pc,
							DefaultMethodSecurityExpressionHandlerBeanFactory.class);
					expressionHandlerRef = pc.getReaderContext().generateBeanName(expressionHandler);
					pc.registerBeanComponent(new BeanComponentDefinition(expressionHandler, expressionHandlerRef));
					this.logger.info("Expressions were enabled for method security but no SecurityExpressionHandler "
							+ "was configured. All hasPermission() expressions will evaluate to false.");
				}
				BeanDefinitionBuilder expressionPreAdviceBldr = BeanDefinitionBuilder
						.rootBeanDefinition(ExpressionBasedPreInvocationAdvice.class);
				expressionPreAdviceBldr.addPropertyReference("expressionHandler", expressionHandlerRef);
				preInvocationVoterBldr.addConstructorArgValue(expressionPreAdviceBldr.getBeanDefinition());
				BeanDefinitionBuilder expressionPostAdviceBldr = BeanDefinitionBuilder
						.rootBeanDefinition(ExpressionBasedPostInvocationAdvice.class);
				expressionPostAdviceBldr.addConstructorArgReference(expressionHandlerRef);
				afterInvocationBldr.addConstructorArgValue(expressionPostAdviceBldr.getBeanDefinition());
				BeanDefinitionBuilder annotationInvocationFactory = BeanDefinitionBuilder
						.rootBeanDefinition(ExpressionBasedAnnotationAttributeFactory.class);
				annotationInvocationFactory.addConstructorArgReference(expressionHandlerRef);
				mds.addConstructorArgValue(annotationInvocationFactory.getBeanDefinition());
			}
			preInvocationVoter = preInvocationVoterBldr.getBeanDefinition();
			afterInvocationProviders.add(afterInvocationBldr.getBeanDefinition());
			delegates.add(mds.getBeanDefinition());
		}
		if (useSecured) {
			delegates.add(BeanDefinitionBuilder.rootBeanDefinition(SecuredAnnotationSecurityMetadataSource.class)
					.getBeanDefinition());
		}
		if (jsr250Enabled) {
			RootBeanDefinition jsrMetadataSource = registerWithDefaultRolePrefix(pc,
					Jsr250MethodSecurityMetadataSourceBeanFactory.class);
			delegates.add(jsrMetadataSource);
		}
		// Now create a Map<String, ConfigAttribute> for each <protect-pointcut>
		// sub-element
		Map<String, List<ConfigAttribute>> pointcutMap = parseProtectPointcuts(pc,
				DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT));
		if (pointcutMap.size() > 0) {
			if (useAspectJ) {
				pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source);
			}
			// Only add it if there are actually any pointcuts defined.
			BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
			BeanReference ref = new RuntimeBeanReference(
					pc.getReaderContext().generateBeanName(mapBasedMetadataSource));
			delegates.add(ref);
			pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, ref.getBeanName()));
			registerProtectPointcutPostProcessor(pc, pointcutMap, ref, source);
		}
		BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, delegates, source);
		// Check for additional after-invocation-providers..
		List<Element> afterInvocationElts = DomUtils.getChildElementsByTagName(element,
				Elements.AFTER_INVOCATION_PROVIDER);
		for (Element elt : afterInvocationElts) {
			afterInvocationProviders.add(new RuntimeBeanReference(elt.getAttribute(ATT_REF)));
		}
		String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
		if (!StringUtils.hasText(accessManagerId)) {
			accessManagerId = registerAccessManager(pc, jsr250Enabled, preInvocationVoter);
		}
		String authMgrRef = element.getAttribute(ATT_AUTHENTICATION_MANAGER_REF);
		String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
		BeanReference interceptor = registerMethodSecurityInterceptor(pc, authMgrRef, accessManagerId, runAsManagerId,
				metadataSource, afterInvocationProviders, source, useAspectJ);
		if (useAspectJ) {
			BeanDefinitionBuilder aspect = BeanDefinitionBuilder.rootBeanDefinition(
					"org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect");
			aspect.setFactoryMethod("aspectOf");
			aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			aspect.addPropertyValue("securityInterceptor", interceptor);
			String id = pc.getReaderContext().registerWithGeneratedName(aspect.getBeanDefinition());
			pc.registerBeanComponent(new BeanComponentDefinition(aspect.getBeanDefinition(), id));
		}
		else {
			registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
		}
		pc.popAndRegisterContainingComponent();
		return null;
	}

	/**
	 * Register the default AccessDecisionManager. Adds the special JSR 250 voter jsr-250
	 * is enabled and an expression voter if expression-based access control is enabled.
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private String registerAccessManager(ParserContext pc, boolean jsr250Enabled, BeanDefinition expressionVoter) {
		BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
		ManagedList voters = new ManagedList(4);
		if (expressionVoter != null) {
			voters.add(expressionVoter);
		}
		voters.add(new RootBeanDefinition(RoleVoter.class));
		voters.add(new RootBeanDefinition(AuthenticatedVoter.class));
		if (jsr250Enabled) {
			voters.add(new RootBeanDefinition(Jsr250Voter.class));
		}
		accessMgrBuilder.addConstructorArgValue(voters);
		BeanDefinition accessManager = accessMgrBuilder.getBeanDefinition();
		String id = pc.getReaderContext().generateBeanName(accessManager);
		pc.registerBeanComponent(new BeanComponentDefinition(accessManager, id));
		return id;
	}

	@SuppressWarnings("rawtypes")
	private BeanReference registerDelegatingMethodSecurityMetadataSource(ParserContext pc, ManagedList delegates,
			Object source) {
		RootBeanDefinition delegatingMethodSecurityMetadataSource = new RootBeanDefinition(
				DelegatingMethodSecurityMetadataSource.class);
		delegatingMethodSecurityMetadataSource.setSource(source);
		delegatingMethodSecurityMetadataSource.getConstructorArgumentValues().addGenericArgumentValue(delegates);
		String id = pc.getReaderContext().generateBeanName(delegatingMethodSecurityMetadataSource);
		pc.registerBeanComponent(new BeanComponentDefinition(delegatingMethodSecurityMetadataSource, id));

		return new RuntimeBeanReference(id);
	}

	private void registerProtectPointcutPostProcessor(ParserContext parserContext,
			Map<String, List<ConfigAttribute>> pointcutMap, BeanReference mapBasedMethodSecurityMetadataSource,
			Object source) {
		RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class);
		ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		ppbp.setSource(source);
		ppbp.getConstructorArgumentValues().addGenericArgumentValue(mapBasedMethodSecurityMetadataSource);
		ppbp.getPropertyValues().addPropertyValue("pointcutMap", pointcutMap);
		parserContext.getReaderContext().registerWithGeneratedName(ppbp);
	}

	private Map<String, List<ConfigAttribute>> parseProtectPointcuts(ParserContext parserContext,
			List<Element> protectPointcutElts) {
		Map<String, List<ConfigAttribute>> pointcutMap = new LinkedHashMap<>();
		for (Element childElt : protectPointcutElts) {
			String accessConfig = childElt.getAttribute(ATT_ACCESS);
			String expression = childElt.getAttribute(ATT_EXPRESSION);
			if (!StringUtils.hasText(accessConfig)) {
				parserContext.getReaderContext().error("Access configuration required",
						parserContext.extractSource(childElt));
			}
			if (!StringUtils.hasText(expression)) {
				parserContext.getReaderContext().error("Pointcut expression required",
						parserContext.extractSource(childElt));
			}
			String[] attributeTokens = StringUtils.commaDelimitedListToStringArray(accessConfig);
			List<ConfigAttribute> attributes = new ArrayList<>(attributeTokens.length);
			for (String token : attributeTokens) {
				attributes.add(new SecurityConfig(token));
			}
			pointcutMap.put(expression, attributes);
		}
		return pointcutMap;
	}

	private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String authMgrRef, String accessManagerId,
			String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders,
			Object source, boolean useAspectJ) {
		BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(
				useAspectJ ? AspectJMethodSecurityInterceptor.class : MethodSecurityInterceptor.class);
		bldr.getRawBeanDefinition().setSource(source);
		bldr.addPropertyReference("accessDecisionManager", accessManagerId);
		RootBeanDefinition authMgr = new RootBeanDefinition(AuthenticationManagerDelegator.class);
		authMgr.getConstructorArgumentValues().addGenericArgumentValue(authMgrRef);
		bldr.addPropertyValue("authenticationManager", authMgr);
		bldr.addPropertyValue("securityMetadataSource", metadataSource);
		if (StringUtils.hasText(runAsManagerId)) {
			bldr.addPropertyReference("runAsManager", runAsManagerId);
		}
		if (!afterInvocationProviders.isEmpty()) {
			BeanDefinition afterInvocationManager;
			afterInvocationManager = new RootBeanDefinition(AfterInvocationProviderManager.class);
			afterInvocationManager.getPropertyValues().addPropertyValue("providers", afterInvocationProviders);
			bldr.addPropertyValue("afterInvocationManager", afterInvocationManager);
		}
		BeanDefinition bean = bldr.getBeanDefinition();
		String id = pc.getReaderContext().generateBeanName(bean);
		pc.registerBeanComponent(new BeanComponentDefinition(bean, id));
		return new RuntimeBeanReference(id);
	}

	private void registerAdvisor(ParserContext parserContext, BeanReference interceptor, BeanReference metadataSource,
			Object source, String adviceOrder) {
		if (parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR)) {
			parserContext.getReaderContext().error("Duplicate <global-method-security> detected.", source);
		}
		RootBeanDefinition advisor = new RootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class);
		if (StringUtils.hasText(adviceOrder)) {
			advisor.getPropertyValues().addPropertyValue("order", adviceOrder);
		}
		// advisor must be an infrastructure bean as Spring's
		// InfrastructureAdvisorAutoProxyCreator will ignore it
		// otherwise
		advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		advisor.setSource(source);
		advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor.getBeanName());
		advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource);
		advisor.getConstructorArgumentValues().addGenericArgumentValue(metadataSource.getBeanName());
		parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR, advisor);
	}

	private RootBeanDefinition registerWithDefaultRolePrefix(ParserContext pc,
			Class<? extends AbstractGrantedAuthorityDefaultsBeanFactory> beanFactoryClass) {
		RootBeanDefinition beanFactoryDefinition = new RootBeanDefinition(beanFactoryClass);
		String beanFactoryRef = pc.getReaderContext().generateBeanName(beanFactoryDefinition);
		pc.getRegistry().registerBeanDefinition(beanFactoryRef, beanFactoryDefinition);
		RootBeanDefinition bean = new RootBeanDefinition();
		bean.setFactoryBeanName(beanFactoryRef);
		bean.setFactoryMethodName("getBean");
		return bean;
	}

	/**
	 * Delays the lookup of the AuthenticationManager within MethodSecurityInterceptor, to
	 * prevent issues like SEC-933.
	 *
	 * @author Luke Taylor
	 * @since 3.0
	 */
	static final class AuthenticationManagerDelegator implements AuthenticationManager, BeanFactoryAware {

		private AuthenticationManager delegate;

		private final Object delegateMonitor = new Object();

		private BeanFactory beanFactory;

		private final String authMgrBean;

		AuthenticationManagerDelegator(String authMgrBean) {
			this.authMgrBean = StringUtils.hasText(authMgrBean) ? authMgrBean : BeanIds.AUTHENTICATION_MANAGER;
		}

		@Override
		public Authentication authenticate(Authentication authentication) throws AuthenticationException {
			synchronized (this.delegateMonitor) {
				if (this.delegate == null) {
					Assert.state(this.beanFactory != null,
							() -> "BeanFactory must be set to resolve " + this.authMgrBean);
					try {
						this.delegate = this.beanFactory.getBean(this.authMgrBean, AuthenticationManager.class);
					}
					catch (NoSuchBeanDefinitionException ex) {
						if (BeanIds.AUTHENTICATION_MANAGER.equals(ex.getBeanName())) {
							throw new NoSuchBeanDefinitionException(BeanIds.AUTHENTICATION_MANAGER,
									AuthenticationManagerFactoryBean.MISSING_BEAN_ERROR_MESSAGE);
						}
						throw ex;
					}
				}
			}
			return this.delegate.authenticate(authentication);
		}

		@Override
		public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
			this.beanFactory = beanFactory;
		}

	}

	static class Jsr250MethodSecurityMetadataSourceBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory {

		private Jsr250MethodSecurityMetadataSource source = new Jsr250MethodSecurityMetadataSource();

		Jsr250MethodSecurityMetadataSource getBean() {
			this.source.setDefaultRolePrefix(this.rolePrefix);
			return this.source;
		}

	}

	static class DefaultMethodSecurityExpressionHandlerBeanFactory extends AbstractGrantedAuthorityDefaultsBeanFactory {

		private DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();

		DefaultMethodSecurityExpressionHandler getBean() {
			this.handler.setDefaultRolePrefix(this.rolePrefix);
			return this.handler;
		}

	}

	abstract static class AbstractGrantedAuthorityDefaultsBeanFactory implements ApplicationContextAware {

		protected String rolePrefix = "ROLE_";

		@Override
		public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
			String[] grantedAuthorityDefaultsBeanNames = applicationContext
					.getBeanNamesForType(GrantedAuthorityDefaults.class);
			if (grantedAuthorityDefaultsBeanNames.length == 1) {
				GrantedAuthorityDefaults grantedAuthorityDefaults = applicationContext
						.getBean(grantedAuthorityDefaultsBeanNames[0], GrantedAuthorityDefaults.class);
				this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
			}
		}

	}

	/**
	 * Delays setting a bean of a given name to be lazyily initialized until after all the
	 * beans are registered.
	 *
	 * @author Rob Winch
	 * @since 3.2
	 */
	private static final class LazyInitBeanDefinitionRegistryPostProcessor
			implements BeanDefinitionRegistryPostProcessor {

		private final String beanName;

		private LazyInitBeanDefinitionRegistryPostProcessor(String beanName) {
			this.beanName = beanName;
		}

		@Override
		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
			if (!registry.containsBeanDefinition(this.beanName)) {
				return;
			}
			BeanDefinition beanDefinition = registry.getBeanDefinition(this.beanName);
			beanDefinition.setLazyInit(true);
		}

		@Override
		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		}

	}

}

相关信息

spring security 源码目录

相关文章

spring security AspectJMethodMatcher 源码

spring security InterceptMethodsBeanDefinitionDecorator 源码

spring security MethodConfigUtils 源码

spring security MethodSecurityBeanDefinitionParser 源码

spring security MethodSecurityMetadataSourceBeanDefinitionParser 源码

spring security PointcutDelegatingAuthorizationManager 源码

spring security PrefixBasedMethodMatcher 源码

spring security ProtectPointcutPostProcessor 源码

spring security package-info 源码

0  赞