diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java index ec33c902f5..8ca065a99d 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.java @@ -40,6 +40,7 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.expression.BeanResolver; +import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.web.FilterChainProxy; @@ -82,12 +83,15 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder .getContextHolderStrategy(); + private AnnotationTemplateExpressionDefaults templateDefaults; + @Override @SuppressWarnings("deprecation") public void addArgumentResolvers(List argumentResolvers) { AuthenticationPrincipalArgumentResolver authenticationPrincipalResolver = new AuthenticationPrincipalArgumentResolver(); authenticationPrincipalResolver.setBeanResolver(this.beanResolver); authenticationPrincipalResolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy); + authenticationPrincipalResolver.setTemplateDefaults(this.templateDefaults); argumentResolvers.add(authenticationPrincipalResolver); argumentResolvers .add(new org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver()); @@ -109,6 +113,9 @@ class WebMvcSecurityConfiguration implements WebMvcConfigurer, ApplicationContex if (applicationContext.getBeanNamesForType(SecurityContextHolderStrategy.class).length == 1) { this.securityContextHolderStrategy = applicationContext.getBean(SecurityContextHolderStrategy.class); } + if (applicationContext.getBeanNamesForType(AnnotationTemplateExpressionDefaults.class).length == 1) { + this.templateDefaults = applicationContext.getBean(AnnotationTemplateExpressionDefaults.class); + } } /** diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java index 69c6e75c51..457d3c83f1 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager; import org.springframework.security.authentication.password.ReactiveCompromisedPasswordChecker; import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService; import org.springframework.security.core.userdetails.ReactiveUserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; @@ -120,12 +121,14 @@ class ServerHttpSecurityConfiguration { } @Bean - AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver() { + AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver( + ObjectProvider templateDefaults) { AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver( this.adapterRegistry); if (this.beanFactory != null) { resolver.setBeanResolver(new BeanFactoryResolver(this.beanFactory)); } + templateDefaults.ifAvailable(resolver::setTemplateDefaults); return resolver; } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfiguration.java index ca0d49d97f..b41bdcfb6f 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfiguration.java @@ -35,6 +35,7 @@ import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.ObservationAuthorizationManager; import org.springframework.security.authorization.SpringAuthorizationEventPublisher; +import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor; @@ -82,6 +83,8 @@ final class WebSocketMessageBrokerSecurityConfiguration private ApplicationContext context; + private AnnotationTemplateExpressionDefaults templateDefaults; + WebSocketMessageBrokerSecurityConfiguration(ApplicationContext context) { this.context = context; } @@ -90,6 +93,7 @@ final class WebSocketMessageBrokerSecurityConfiguration public void addArgumentResolvers(List argumentResolvers) { AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver(); resolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy); + resolver.setTemplateDefaults(this.templateDefaults); argumentResolvers.add(resolver); } @@ -128,6 +132,11 @@ final class WebSocketMessageBrokerSecurityConfiguration this.observationRegistry = observationRegistry; } + @Autowired(required = false) + void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { + this.templateDefaults = templateDefaults; + } + @Override public void afterSingletonsInstantiated() { SimpleUrlHandlerMapping mapping = getBeanOrNull(SIMPLE_URL_HANDLER_MAPPING_BEAN_NAME, diff --git a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java index e833c6f3f7..05667a6d17 100644 --- a/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/websocket/WebSocketMessageBrokerSecurityBeanDefinitionParser.java @@ -305,6 +305,8 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements private static final String CUSTOM_ARG_RESOLVERS_PROP = "customArgumentResolvers"; + private static final String TEMPLATE_EXPRESSION_BEAN_ID = "templateDefaults"; + private final String inboundSecurityInterceptorId; private final boolean sameOriginDisabled; @@ -327,7 +329,13 @@ public final class WebSocketMessageBrokerSecurityBeanDefinitionParser implements if (current != null) { argResolvers.addAll((ManagedList) current.getValue()); } - argResolvers.add(new RootBeanDefinition(AuthenticationPrincipalArgumentResolver.class)); + RootBeanDefinition beanDefinition = new RootBeanDefinition( + AuthenticationPrincipalArgumentResolver.class); + if (registry.containsBeanDefinition(TEMPLATE_EXPRESSION_BEAN_ID)) { + beanDefinition.getPropertyValues() + .add(TEMPLATE_EXPRESSION_BEAN_ID, new RuntimeBeanReference(TEMPLATE_EXPRESSION_BEAN_ID)); + } + argResolvers.add(beanDefinition); bd.getPropertyValues().add(CUSTOM_ARG_RESOLVERS_PROP, argResolvers); if (!registry.containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) { PropertyValue pathMatcherProp = bd.getPropertyValues().getPropertyValue("pathMatcher");