|
|
|
|
@ -29,14 +29,12 @@ import jakarta.servlet.http.HttpServletRequest;
@@ -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
@@ -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; |
|
|
|
|
|