|
@@ -16,22 +16,17 @@
|
|
|
|
|
|
package org.springframework.security.config.annotation.method.configuration;
|
|
|
|
|
|
-import java.util.function.Consumer;
|
|
|
-import java.util.function.Supplier;
|
|
|
-
|
|
|
import io.micrometer.observation.ObservationRegistry;
|
|
|
-import org.aopalliance.aop.Advice;
|
|
|
import org.aopalliance.intercept.MethodInterceptor;
|
|
|
-import org.aopalliance.intercept.MethodInvocation;
|
|
|
-import org.jetbrains.annotations.NotNull;
|
|
|
-import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
import org.springframework.aop.Pointcut;
|
|
|
import org.springframework.aop.framework.AopInfrastructureBean;
|
|
|
+import org.springframework.beans.BeansException;
|
|
|
import org.springframework.beans.factory.ObjectProvider;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
+import org.springframework.context.ApplicationContextAware;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
import org.springframework.context.annotation.Fallback;
|
|
@@ -39,18 +34,15 @@ import org.springframework.context.annotation.Role;
|
|
|
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
|
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
|
|
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
|
|
-import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|
|
-import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
|
|
+import org.springframework.security.authorization.ObservationReactiveAuthorizationManager;
|
|
|
import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
|
|
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
|
|
|
-import org.springframework.security.authorization.method.MethodInvocationResult;
|
|
|
import org.springframework.security.authorization.method.PostAuthorizeReactiveAuthorizationManager;
|
|
|
import org.springframework.security.authorization.method.PostFilterAuthorizationReactiveMethodInterceptor;
|
|
|
import org.springframework.security.authorization.method.PreAuthorizeReactiveAuthorizationManager;
|
|
|
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
|
|
|
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
|
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
|
-import org.springframework.util.function.SingletonSupplier;
|
|
|
|
|
|
/**
|
|
|
* Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
|
|
@@ -58,59 +50,105 @@ import org.springframework.util.function.SingletonSupplier;
|
|
|
* @author Evgeniy Cheban
|
|
|
* @since 5.8
|
|
|
*/
|
|
|
-@Configuration(proxyBeanMethods = false)
|
|
|
-final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements AopInfrastructureBean {
|
|
|
+@Configuration(value = "_reactiveMethodSecurityConfiguration", proxyBeanMethods = false)
|
|
|
+final class ReactiveAuthorizationManagerMethodSecurityConfiguration
|
|
|
+ implements AopInfrastructureBean, ApplicationContextAware {
|
|
|
+
|
|
|
+ private static final Pointcut preFilterPointcut = new PreFilterAuthorizationReactiveMethodInterceptor()
|
|
|
+ .getPointcut();
|
|
|
+
|
|
|
+ private static final Pointcut preAuthorizePointcut = AuthorizationManagerBeforeReactiveMethodInterceptor
|
|
|
+ .preAuthorize()
|
|
|
+ .getPointcut();
|
|
|
+
|
|
|
+ private static final Pointcut postAuthorizePointcut = AuthorizationManagerAfterReactiveMethodInterceptor
|
|
|
+ .postAuthorize()
|
|
|
+ .getPointcut();
|
|
|
+
|
|
|
+ private static final Pointcut postFilterPointcut = new PostFilterAuthorizationReactiveMethodInterceptor()
|
|
|
+ .getPointcut();
|
|
|
+
|
|
|
+ private PreFilterAuthorizationReactiveMethodInterceptor preFilterMethodInterceptor = new PreFilterAuthorizationReactiveMethodInterceptor();
|
|
|
+
|
|
|
+ private PreAuthorizeReactiveAuthorizationManager preAuthorizeAuthorizationManager = new PreAuthorizeReactiveAuthorizationManager();
|
|
|
+
|
|
|
+ private PostAuthorizeReactiveAuthorizationManager postAuthorizeAuthorizationManager = new PostAuthorizeReactiveAuthorizationManager();
|
|
|
+
|
|
|
+ private PostFilterAuthorizationReactiveMethodInterceptor postFilterMethodInterceptor = new PostFilterAuthorizationReactiveMethodInterceptor();
|
|
|
+
|
|
|
+ private AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeMethodInterceptor;
|
|
|
+
|
|
|
+ private AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeMethodInterceptor;
|
|
|
+
|
|
|
+ @Autowired(required = false)
|
|
|
+ ReactiveAuthorizationManagerMethodSecurityConfiguration(MethodSecurityExpressionHandler expressionHandler) {
|
|
|
+ if (expressionHandler != null) {
|
|
|
+ this.preFilterMethodInterceptor = new PreFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
|
|
|
+ this.preAuthorizeAuthorizationManager = new PreAuthorizeReactiveAuthorizationManager(expressionHandler);
|
|
|
+ this.postFilterMethodInterceptor = new PostFilterAuthorizationReactiveMethodInterceptor(expressionHandler);
|
|
|
+ this.postAuthorizeAuthorizationManager = new PostAuthorizeReactiveAuthorizationManager(expressionHandler);
|
|
|
+ }
|
|
|
+ this.preAuthorizeMethodInterceptor = AuthorizationManagerBeforeReactiveMethodInterceptor
|
|
|
+ .preAuthorize(this.preAuthorizeAuthorizationManager);
|
|
|
+ this.postAuthorizeMethodInterceptor = AuthorizationManagerAfterReactiveMethodInterceptor
|
|
|
+ .postAuthorize(this.postAuthorizeAuthorizationManager);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setApplicationContext(ApplicationContext context) throws BeansException {
|
|
|
+ this.preAuthorizeAuthorizationManager.setApplicationContext(context);
|
|
|
+ this.postAuthorizeAuthorizationManager.setApplicationContext(context);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Autowired(required = false)
|
|
|
+ void setTemplateDefaults(PrePostTemplateDefaults templateDefaults) {
|
|
|
+ this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
|
+ this.preAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
|
+ this.postAuthorizeAuthorizationManager.setTemplateDefaults(templateDefaults);
|
|
|
+ this.postFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Autowired(required = false)
|
|
|
+ void setObservationRegistry(ObservationRegistry registry) {
|
|
|
+ if (registry.isNoop()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.preAuthorizeMethodInterceptor = AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(
|
|
|
+ new ObservationReactiveAuthorizationManager<>(registry, this.preAuthorizeAuthorizationManager));
|
|
|
+ this.postAuthorizeMethodInterceptor = AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(
|
|
|
+ new ObservationReactiveAuthorizationManager<>(registry, this.postAuthorizeAuthorizationManager));
|
|
|
+ }
|
|
|
|
|
|
@Bean
|
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
|
- static MethodInterceptor preFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
|
|
|
- ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
|
- PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
|
|
|
- expressionHandler);
|
|
|
- return new DeferringMethodInterceptor<>(interceptor,
|
|
|
- (i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
|
|
|
+ static MethodInterceptor preFilterAuthorizationMethodInterceptor(
|
|
|
+ ObjectProvider<ReactiveAuthorizationManagerMethodSecurityConfiguration> _reactiveMethodSecurityConfiguration) {
|
|
|
+ return new DeferringMethodInterceptor<>(preFilterPointcut,
|
|
|
+ () -> _reactiveMethodSecurityConfiguration.getObject().preFilterMethodInterceptor);
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
|
static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
|
|
|
- MethodSecurityExpressionHandler expressionHandler,
|
|
|
- ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
|
- ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
|
|
|
- PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
|
|
|
- expressionHandler);
|
|
|
- manager.setApplicationContext(context);
|
|
|
- ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(manager, registryProvider);
|
|
|
- AuthorizationAdvisor interceptor = AuthorizationManagerBeforeReactiveMethodInterceptor
|
|
|
- .preAuthorize(authorizationManager);
|
|
|
- return new DeferringMethodInterceptor<>(interceptor,
|
|
|
- (i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
|
|
|
+ ObjectProvider<ReactiveAuthorizationManagerMethodSecurityConfiguration> _reactiveMethodSecurityConfiguration) {
|
|
|
+ return new DeferringMethodInterceptor<>(preAuthorizePointcut,
|
|
|
+ () -> _reactiveMethodSecurityConfiguration.getObject().preAuthorizeMethodInterceptor);
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
|
- static MethodInterceptor postFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
|
|
|
- ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
|
- PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
|
|
|
- expressionHandler);
|
|
|
- return new DeferringMethodInterceptor<>(interceptor,
|
|
|
- (i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
|
|
|
+ static MethodInterceptor postFilterAuthorizationMethodInterceptor(
|
|
|
+ ObjectProvider<ReactiveAuthorizationManagerMethodSecurityConfiguration> _reactiveMethodSecurityConfiguration) {
|
|
|
+ return new DeferringMethodInterceptor<>(postFilterPointcut,
|
|
|
+ () -> _reactiveMethodSecurityConfiguration.getObject().postFilterMethodInterceptor);
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
|
static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
|
|
|
- MethodSecurityExpressionHandler expressionHandler,
|
|
|
- ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
|
- ObjectProvider<ObservationRegistry> registryProvider, ApplicationContext context) {
|
|
|
- PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
|
|
|
- expressionHandler);
|
|
|
- manager.setApplicationContext(context);
|
|
|
- ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(manager, registryProvider);
|
|
|
- AuthorizationAdvisor interceptor = AuthorizationManagerAfterReactiveMethodInterceptor
|
|
|
- .postAuthorize(authorizationManager);
|
|
|
- return new DeferringMethodInterceptor<>(interceptor,
|
|
|
- (i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
|
|
|
+ ObjectProvider<ReactiveAuthorizationManagerMethodSecurityConfiguration> _reactiveMethodSecurityConfiguration) {
|
|
|
+ return new DeferringMethodInterceptor<>(postAuthorizePointcut,
|
|
|
+ () -> _reactiveMethodSecurityConfiguration.getObject().postAuthorizeMethodInterceptor);
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
@@ -125,55 +163,4 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements A
|
|
|
return handler;
|
|
|
}
|
|
|
|
|
|
- static <T> ReactiveAuthorizationManager<T> manager(ReactiveAuthorizationManager<T> delegate,
|
|
|
- ObjectProvider<ObservationRegistry> registryProvider) {
|
|
|
- return new DeferringObservationReactiveAuthorizationManager<>(registryProvider, delegate);
|
|
|
- }
|
|
|
-
|
|
|
- private static final class DeferringMethodInterceptor<M extends AuthorizationAdvisor>
|
|
|
- implements AuthorizationAdvisor {
|
|
|
-
|
|
|
- private final Pointcut pointcut;
|
|
|
-
|
|
|
- private final int order;
|
|
|
-
|
|
|
- private final Supplier<M> delegate;
|
|
|
-
|
|
|
- DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
|
|
|
- this.pointcut = delegate.getPointcut();
|
|
|
- this.order = delegate.getOrder();
|
|
|
- this.delegate = SingletonSupplier.of(() -> {
|
|
|
- supplier.accept(delegate);
|
|
|
- return delegate;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- @Nullable
|
|
|
- @Override
|
|
|
- public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
|
|
|
- return this.delegate.get().invoke(invocation);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Pointcut getPointcut() {
|
|
|
- return this.pointcut;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Advice getAdvice() {
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int getOrder() {
|
|
|
- return this.order;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean isPerInstance() {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
}
|