瀏覽代碼

Merge branch '6.1.x' into 6.2.x

Marcus Hert Da Coregio 1 年之前
父節點
當前提交
d385b53e3c

+ 40 - 61
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java

@@ -29,14 +29,12 @@ import jakarta.servlet.http.HttpServletRequest;
 import org.springframework.beans.BeanMetadataElement;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 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.RegisteredBean;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.annotation.Bean;
@@ -113,86 +111,67 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex
 		}
 	}
 
-	@Bean
-	static SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor() {
-		return new SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor();
-	}
-
 	/**
-	 * Used to ensure Spring MVC request matching is cached. Creates a
-	 * {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named
+	 * Used to ensure Spring MVC request matching is cached.
+	 *
+	 * Creates a {@link BeanDefinitionRegistryPostProcessor} that detects if a bean named
 	 * HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME is defined. If so, it moves the
 	 * AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME to another bean name
 	 * and then adds a {@link CompositeFilter} that contains
 	 * {@link HandlerMappingIntrospector#createCacheFilter()} and the original
 	 * FilterChainProxy under the original Bean name.
-	 *
 	 * @return
 	 */
-	static class SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor
-			implements BeanDefinitionRegistryPostProcessor {
-
-		@Override
-		public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-			if (!registry.containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
-				return;
+	@Bean
+	static BeanDefinitionRegistryPostProcessor springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor() {
+		return new BeanDefinitionRegistryPostProcessor() {
+			@Override
+			public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
 			}
 
-			BeanDefinition hmiRequestTransformer = BeanDefinitionBuilder
-				.rootBeanDefinition(HandlerMappingIntrospectorRequestTransformer.class)
-				.addConstructorArgReference(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)
-				.getBeanDefinition();
-			registry.registerBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer",
-					hmiRequestTransformer);
-
-			BeanDefinition filterChainProxy = registry
-				.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
-
-			BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
-				.rootBeanDefinition(HandlerMappingIntrospectorCachFilterFactoryBean.class)
-				.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
-			ManagedList<BeanMetadataElement> filters = new ManagedList<>();
-			filters.add(hmiCacheFilterBldr.getBeanDefinition());
-			filters.add(filterChainProxy);
-			BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
-				.rootBeanDefinition(CompositeFilterChainProxy.class)
-				.addConstructorArgValue(filters);
-
-			registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
-			registry.registerBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME,
-					compositeSpringSecurityFilterChainBldr.getBeanDefinition());
-		}
-
-		@Override
-		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+			@Override
+			public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
+				if (!registry.containsBeanDefinition(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
+					return;
+				}
 
-		}
+				String hmiRequestTransformerBeanName = HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + "RequestTransformer";
+				if (!registry.containsBeanDefinition(hmiRequestTransformerBeanName)) {
+					BeanDefinition hmiRequestTransformer = BeanDefinitionBuilder
+						.rootBeanDefinition(HandlerMappingIntrospectorRequestTransformer.class)
+						.addConstructorArgReference(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)
+						.getBeanDefinition();
+					registry.registerBeanDefinition(hmiRequestTransformerBeanName, hmiRequestTransformer);
+				}
 
-	}
+				BeanDefinition filterChainProxy = registry
+					.getBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
 
-	/**
-	 * Used to exclude the
-	 * {@link SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor}
-	 * from AOT processing. See <a href=
-	 * "https://github.com/spring-projects/spring-security/issues/14362">gh-14362</a>
-	 */
-	static class SpringSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilter
-			implements BeanRegistrationExcludeFilter {
+				if (!filterChainProxy.getResolvableType().isInstance(CompositeFilterChainProxy.class)) {
+					BeanDefinitionBuilder hmiCacheFilterBldr = BeanDefinitionBuilder
+						.rootBeanDefinition(HandlerMappingIntrospectorCacheFilterFactoryBean.class)
+						.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
 
-		@Override
-		public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) {
-			Class<?> beanClass = registeredBean.getBeanClass();
-			return SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor.class == beanClass;
-		}
+					ManagedList<BeanMetadataElement> filters = new ManagedList<>();
+					filters.add(hmiCacheFilterBldr.getBeanDefinition());
+					filters.add(filterChainProxy);
+					BeanDefinitionBuilder compositeSpringSecurityFilterChainBldr = BeanDefinitionBuilder
+						.rootBeanDefinition(CompositeFilterChainProxy.class)
+						.addConstructorArgValue(filters);
 
+					registry.removeBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME);
+					registry.registerBeanDefinition(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME,
+							compositeSpringSecurityFilterChainBldr.getBeanDefinition());
+				}
+			}
+		};
 	}
 
 	/**
 	 * {@link FactoryBean} to defer creation of
 	 * {@link HandlerMappingIntrospector#createCacheFilter()}
 	 */
-	static class HandlerMappingIntrospectorCachFilterFactoryBean
+	static class HandlerMappingIntrospectorCacheFilterFactoryBean
 			implements ApplicationContextAware, FactoryBean<Filter> {
 
 		private ApplicationContext applicationContext;

+ 5 - 1
config/src/main/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHints.java

@@ -34,7 +34,11 @@ class WebMvcSecurityConfigurationRuntimeHints implements RuntimeHintsRegistrar {
 		hints.reflection()
 			.registerType(TypeReference
 				.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"),
-					MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
+					MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
+		hints.reflection()
+			.registerType(TypeReference
+				.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean"),
+					MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
 	}
 
 }

+ 0 - 3
config/src/main/resources/META-INF/spring/aot.factories

@@ -4,6 +4,3 @@ org.springframework.security.config.annotation.authentication.configuration.Auth
 org.springframework.aot.hint.RuntimeHintsRegistrar=\
 org.springframework.security.config.aot.hint.OAuth2LoginRuntimeHints,\
 org.springframework.security.config.aot.hint.WebMvcSecurityConfigurationRuntimeHints
-
-org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\
-org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration.SpringSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilter

+ 0 - 53
config/src/test/java/org/springframework/security/config/annotation/web/configuration/SpringSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilterTests.java

@@ -1,53 +0,0 @@
-/*
- * Copyright 2002-2023 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.annotation.web.configuration;
-
-import java.util.List;
-
-import org.junit.jupiter.api.Test;
-
-import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
-import org.springframework.beans.factory.support.RegisteredBean;
-import org.springframework.core.io.support.SpringFactoriesLoader;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.mock;
-
-/**
- * Tests for
- * {@link WebMvcSecurityConfiguration.SpringSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilter}
- *
- * @author Marcus da Coregio
- */
-class SpringSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilterTests {
-
-	@Test
-	void springSecurityHandlerMappingIntrospectorBeanRegistrationExcludeFilterShouldBeExcludedFromAotProcessing()
-			throws ClassNotFoundException {
-		List<BeanRegistrationExcludeFilter> filters = SpringFactoriesLoader
-			.forResourceLocation("META-INF/spring/aot.factories")
-			.load(BeanRegistrationExcludeFilter.class);
-		RegisteredBean registeredBean = mock(RegisteredBean.class);
-		Class<?> clazz = Class.forName(
-				"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$SpringSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor");
-		given(registeredBean.getBeanClass()).willReturn((Class) clazz);
-		boolean isExcluded = filters.stream().anyMatch((f) -> f.isExcludedFromAotProcessing(registeredBean));
-		assertThat(isExcluded).isTrue();
-	}
-
-}

+ 8 - 0
config/src/test/java/org/springframework/security/config/aot/hint/WebMvcSecurityConfigurationRuntimeHintsTests.java

@@ -53,4 +53,12 @@ class WebMvcSecurityConfigurationRuntimeHintsTests {
 			.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints);
 	}
 
+	@Test
+	void handlerMappingIntrospectorCacheFilterFactoryBeanHasHints() {
+		assertThat(RuntimeHintsPredicates.reflection()
+			.onType(TypeReference
+				.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean"))
+			.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.hints);
+	}
+
 }

+ 1 - 1
test/src/main/java/org/springframework/security/test/aot/hint/WebTestUtilsTestRuntimeHints.java

@@ -50,7 +50,7 @@ class WebTestUtilsTestRuntimeHints implements TestRuntimeHintsRegistrar {
 		hints.reflection()
 			.registerType(TypeReference
 				.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"),
-					MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
+					MemberCategory.INVOKE_DECLARED_METHODS);
 	}
 
 	private void registerCsrfTokenRepositoryHints(RuntimeHints hints) {

+ 1 - 2
test/src/test/java/org/springframework/security/test/aot/hint/WebTestUtilsTestRuntimeHintsTests.java

@@ -62,8 +62,7 @@ class WebTestUtilsTestRuntimeHintsTests {
 		assertThat(RuntimeHintsPredicates.reflection()
 			.onType(TypeReference
 				.of("org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy"))
-			.withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
-			.accepts(this.hints);
+			.withMemberCategory(MemberCategory.INVOKE_DECLARED_METHODS)).accepts(this.hints);
 	}
 
 	@Test