2
0
Эх сурвалжийг харах

Merge branch '6.0.x' into 6.1.x

Closes gh-13814
Marcus Da Coregio 1 жил өмнө
parent
commit
59a9aa3268

+ 51 - 4
config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

@@ -16,8 +16,11 @@
 
 package org.springframework.security.config.annotation.method.configuration;
 
+import java.util.function.Supplier;
+
 import io.micrometer.observation.ObservationRegistry;
 import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
 
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.config.BeanDefinition;
@@ -25,6 +28,9 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Role;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
 import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
 import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
 import org.springframework.security.authorization.AuthorizationEventPublisher;
@@ -36,7 +42,9 @@ import org.springframework.security.authorization.method.PostFilterAuthorization
 import org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager;
 import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
+import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
+import org.springframework.util.function.SingletonSupplier;
 
 /**
  * Base {@link Configuration} for enabling Spring Security Method Security.
@@ -59,7 +67,7 @@ final class PrePostMethodSecurityConfiguration {
 		PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
 		strategyProvider.ifAvailable(preFilter::setSecurityContextHolderStrategy);
 		preFilter.setExpressionHandler(
-				expressionHandlerProvider.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, context)));
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		return preFilter;
 	}
 
@@ -73,7 +81,7 @@ final class PrePostMethodSecurityConfiguration {
 			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
 		PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
 		manager.setExpressionHandler(
-				expressionHandlerProvider.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, context)));
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor
 				.preAuthorize(manager(manager, registryProvider));
 		strategyProvider.ifAvailable(preAuthorize::setSecurityContextHolderStrategy);
@@ -91,7 +99,7 @@ final class PrePostMethodSecurityConfiguration {
 			ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
 		PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
 		manager.setExpressionHandler(
-				expressionHandlerProvider.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, context)));
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor
 				.postAuthorize(manager(manager, registryProvider));
 		strategyProvider.ifAvailable(postAuthorize::setSecurityContextHolderStrategy);
@@ -108,7 +116,7 @@ final class PrePostMethodSecurityConfiguration {
 		PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
 		strategyProvider.ifAvailable(postFilter::setSecurityContextHolderStrategy);
 		postFilter.setExpressionHandler(
-				expressionHandlerProvider.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, context)));
+				new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider, defaultsProvider, context));
 		return postFilter;
 	}
 
@@ -125,4 +133,43 @@ final class PrePostMethodSecurityConfiguration {
 		return new DeferringObservationAuthorizationManager<>(registryProvider, delegate);
 	}
 
+	private static final class DeferringMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
+
+		private final Supplier<MethodSecurityExpressionHandler> expressionHandler;
+
+		private DeferringMethodSecurityExpressionHandler(
+				ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
+				ObjectProvider<GrantedAuthorityDefaults> defaultsProvider, ApplicationContext applicationContext) {
+			this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider
+					.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, applicationContext)));
+		}
+
+		@Override
+		public ExpressionParser getExpressionParser() {
+			return this.expressionHandler.get().getExpressionParser();
+		}
+
+		@Override
+		public EvaluationContext createEvaluationContext(Authentication authentication, MethodInvocation invocation) {
+			return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
+		}
+
+		@Override
+		public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
+				MethodInvocation invocation) {
+			return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
+		}
+
+		@Override
+		public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
+			return this.expressionHandler.get().filter(filterTarget, filterExpression, ctx);
+		}
+
+		@Override
+		public void setReturnObject(Object returnObject, EvaluationContext ctx) {
+			this.expressionHandler.get().setReturnObject(returnObject, ctx);
+		}
+
+	}
+
 }