Procházet zdrojové kódy

Correct PostFilterAuthorizationMethodInterceptor Target Type

Previously, `postFilterAuthorizationMethodInterceptor` mistakenly
was published as an `Advisor`. Because `MethodSecurityAdvisorRegistrar`
re-publishes each pre/post annotation interceptor also as an `Advisor`,
this resulted in a duplicate advisor for `@PostFilter`.

Closes gh-15651
Josh Cummings před 1 rokem
rodič
revize
5c604b95fb

+ 1 - 2
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;
 	}
 

+ 27 - 0
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<ConfigurableWebApplicationContext> 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 {