diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java new file mode 100644 index 00000000000..4d534e5cfb4 --- /dev/null +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/DeferringObservationAuthorizationManager.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.method.configuration; + +import java.util.function.Supplier; + +import io.micrometer.observation.ObservationRegistry; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.authorization.ObservationAuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.util.function.SingletonSupplier; + +final class DeferringObservationAuthorizationManager implements AuthorizationManager { + + private final Supplier> delegate; + + DeferringObservationAuthorizationManager(ObjectProvider provider, + AuthorizationManager delegate) { + this.delegate = SingletonSupplier.of(() -> { + ObservationRegistry registry = provider.getIfAvailable(() -> ObservationRegistry.NOOP); + if (registry.isNoop()) { + return delegate; + } + return new ObservationAuthorizationManager<>(registry, delegate); + }); + } + + @Override + public AuthorizationDecision check(Supplier authentication, T object) { + return this.delegate.get().check(authentication, object); + } + +} diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java index a1210652ee7..6fe8deb17c2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/Jsr250MethodSecurityConfiguration.java @@ -26,7 +26,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Role; import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.authorization.ObservationAuthorizationManager; import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor; import org.springframework.security.authorization.method.Jsr250AuthorizationManager; import org.springframework.security.config.core.GrantedAuthorityDefaults; @@ -54,19 +53,12 @@ static Advisor jsr250AuthorizationMethodInterceptor(ObjectProvider jsr250.setRolePrefix(d.getRolePrefix())); SecurityContextHolderStrategy strategy = strategyProvider .getIfAvailable(SecurityContextHolder::getContextHolderStrategy); - ObservationRegistry registry = registryProvider.getIfAvailable(() -> ObservationRegistry.NOOP); - AuthorizationManager manager = manager(jsr250, registry); + AuthorizationManager manager = new DeferringObservationAuthorizationManager<>( + registryProvider, jsr250); AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor .jsr250(manager); interceptor.setSecurityContextHolderStrategy(strategy); return interceptor; } - static AuthorizationManager manager(AuthorizationManager jsr250, ObservationRegistry registry) { - if (registry.isNoop()) { - return jsr250; - } - return new ObservationAuthorizationManager<>(registry, jsr250); - } - } 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 79a5c54fa7c..4a73dff3e1e 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 @@ -29,7 +29,6 @@ import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; import org.springframework.security.authorization.AuthorizationEventPublisher; import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.authorization.ObservationAuthorizationManager; import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor; import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor; import org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager; @@ -120,11 +119,7 @@ private static MethodSecurityExpressionHandler defaultExpressionHandler( static AuthorizationManager manager(AuthorizationManager delegate, ObjectProvider registryProvider) { - ObservationRegistry registry = registryProvider.getIfAvailable(() -> ObservationRegistry.NOOP); - if (registry.isNoop()) { - return delegate; - } - return new ObservationAuthorizationManager<>(registry, delegate); + return new DeferringObservationAuthorizationManager<>(registryProvider, delegate); } } diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java index 9c93ecfb756..71c11ef2883 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/SecuredMethodSecurityConfiguration.java @@ -27,7 +27,6 @@ import org.springframework.context.annotation.Role; import org.springframework.security.access.annotation.Secured; import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.security.authorization.ObservationAuthorizationManager; import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor; import org.springframework.security.authorization.method.SecuredAuthorizationManager; import org.springframework.security.core.context.SecurityContextHolder; @@ -52,19 +51,12 @@ static Advisor securedAuthorizationMethodInterceptor(ObjectProvider ObservationRegistry.NOOP); - AuthorizationManager manager = manager(secured, registry); + AuthorizationManager manager = new DeferringObservationAuthorizationManager<>( + registryProvider, secured); AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor .secured(manager); interceptor.setSecurityContextHolderStrategy(strategy); return interceptor; } - static AuthorizationManager manager(AuthorizationManager jsr250, ObservationRegistry registry) { - if (registry.isNoop()) { - return jsr250; - } - return new ObservationAuthorizationManager<>(registry, jsr250); - } - }