diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java index a0561b58f6..d076cf8c95 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.method.configuration; import org.aopalliance.intercept.MethodInterceptor; -import org.springframework.aop.Advisor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.ApplicationContext; @@ -100,7 +99,7 @@ final class PrePostMethodSecurityConfiguration { @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - Advisor postFilterAuthorizationMethodInterceptor() { + MethodInterceptor postFilterAuthorizationMethodInterceptor() { return this.postFilterAuthorizationMethodInterceptor; } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java index 282c01cffe..ed86697f71 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java @@ -73,6 +73,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** @@ -432,6 +434,18 @@ public class PrePostMethodSecurityConfigurationTests { .autowire(); } + // gh-15651 + @Test + @WithMockUser(roles = "ADMIN") + public void adviseWhenPrePostEnabledThenEachInterceptorRunsExactlyOnce() { + this.spring.register(MethodSecurityServiceConfig.class, CustomMethodSecurityExpressionHandlerConfig.class) + .autowire(); + MethodSecurityExpressionHandler expressionHandler = this.spring.getContext() + .getBean(MethodSecurityExpressionHandler.class); + this.methodSecurityService.manyAnnotations(new ArrayList<>(Arrays.asList("harold", "jonathan", "tim", "bo"))); + verify(expressionHandler, times(4)).createEvaluationContext(any(Supplier.class), any()); + } + private static Consumer disallowBeanOverriding() { return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false); } @@ -491,6 +505,19 @@ public class PrePostMethodSecurityConfigurationTests { } + @EnableMethodSecurity + static class CustomMethodSecurityExpressionHandlerConfig { + + private final MethodSecurityExpressionHandler expressionHandler = spy( + new DefaultMethodSecurityExpressionHandler()); + + @Bean + MethodSecurityExpressionHandler methodSecurityExpressionHandler() { + return this.expressionHandler; + } + + } + @EnableMethodSecurity static class CustomPermissionEvaluatorConfig {