|
@@ -16,9 +16,18 @@
|
|
|
|
|
|
package org.springframework.security.config.annotation.method.configuration;
|
|
package org.springframework.security.config.annotation.method.configuration;
|
|
|
|
|
|
|
|
+import java.util.function.Consumer;
|
|
|
|
+import java.util.function.Supplier;
|
|
|
|
+
|
|
import io.micrometer.observation.ObservationRegistry;
|
|
import io.micrometer.observation.ObservationRegistry;
|
|
|
|
+import org.aopalliance.aop.Advice;
|
|
|
|
+import org.aopalliance.intercept.MethodInterceptor;
|
|
import org.aopalliance.intercept.MethodInvocation;
|
|
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.factory.ObjectProvider;
|
|
import org.springframework.beans.factory.ObjectProvider;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
@@ -29,6 +38,7 @@ import org.springframework.security.access.expression.method.DefaultMethodSecuri
|
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
|
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
|
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
|
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
|
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
|
|
|
+import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
|
import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.AuthorizationManagerAfterReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.AuthorizationManagerBeforeReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.MethodInvocationResult;
|
|
import org.springframework.security.authorization.method.MethodInvocationResult;
|
|
@@ -38,6 +48,7 @@ import org.springframework.security.authorization.method.PreAuthorizeReactiveAut
|
|
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.PreFilterAuthorizationReactiveMethodInterceptor;
|
|
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
|
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
|
|
+import org.springframework.util.function.SingletonSupplier;
|
|
|
|
|
|
/**
|
|
/**
|
|
* Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
|
|
* Configuration for a {@link ReactiveAuthenticationManager} based Method Security.
|
|
@@ -46,54 +57,56 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
|
* @since 5.8
|
|
* @since 5.8
|
|
*/
|
|
*/
|
|
@Configuration(proxyBeanMethods = false)
|
|
@Configuration(proxyBeanMethods = false)
|
|
-final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
|
|
|
|
|
|
+final class ReactiveAuthorizationManagerMethodSecurityConfiguration implements AopInfrastructureBean {
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
- static PreFilterAuthorizationReactiveMethodInterceptor preFilterInterceptor(
|
|
|
|
- MethodSecurityExpressionHandler expressionHandler,
|
|
|
|
|
|
+ static MethodInterceptor preFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
|
|
PreFilterAuthorizationReactiveMethodInterceptor interceptor = new PreFilterAuthorizationReactiveMethodInterceptor(
|
|
expressionHandler);
|
|
expressionHandler);
|
|
- defaultsObjectProvider.ifAvailable(interceptor::setTemplateDefaults);
|
|
|
|
- return interceptor;
|
|
|
|
|
|
+ return new DeferringMethodInterceptor<>(interceptor,
|
|
|
|
+ (i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
|
|
}
|
|
}
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
- static AuthorizationManagerBeforeReactiveMethodInterceptor preAuthorizeInterceptor(
|
|
|
|
|
|
+ static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
|
|
MethodSecurityExpressionHandler expressionHandler,
|
|
MethodSecurityExpressionHandler expressionHandler,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
ObjectProvider<ObservationRegistry> registryProvider) {
|
|
ObjectProvider<ObservationRegistry> registryProvider) {
|
|
PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
|
|
PreAuthorizeReactiveAuthorizationManager manager = new PreAuthorizeReactiveAuthorizationManager(
|
|
expressionHandler);
|
|
expressionHandler);
|
|
- defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults);
|
|
|
|
ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(manager, registryProvider);
|
|
ReactiveAuthorizationManager<MethodInvocation> authorizationManager = manager(manager, registryProvider);
|
|
- return AuthorizationManagerBeforeReactiveMethodInterceptor.preAuthorize(authorizationManager);
|
|
|
|
|
|
+ AuthorizationAdvisor interceptor = AuthorizationManagerBeforeReactiveMethodInterceptor
|
|
|
|
+ .preAuthorize(authorizationManager);
|
|
|
|
+ return new DeferringMethodInterceptor<>(interceptor,
|
|
|
|
+ (i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
|
|
}
|
|
}
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
- static PostFilterAuthorizationReactiveMethodInterceptor postFilterInterceptor(
|
|
|
|
- MethodSecurityExpressionHandler expressionHandler,
|
|
|
|
|
|
+ static MethodInterceptor postFilterAuthorizationMethodInterceptor(MethodSecurityExpressionHandler expressionHandler,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider) {
|
|
PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
|
|
PostFilterAuthorizationReactiveMethodInterceptor interceptor = new PostFilterAuthorizationReactiveMethodInterceptor(
|
|
expressionHandler);
|
|
expressionHandler);
|
|
- defaultsObjectProvider.ifAvailable(interceptor::setTemplateDefaults);
|
|
|
|
- return interceptor;
|
|
|
|
|
|
+ return new DeferringMethodInterceptor<>(interceptor,
|
|
|
|
+ (i) -> defaultsObjectProvider.ifAvailable(i::setTemplateDefaults));
|
|
}
|
|
}
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
|
- static AuthorizationManagerAfterReactiveMethodInterceptor postAuthorizeInterceptor(
|
|
|
|
|
|
+ static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
|
|
MethodSecurityExpressionHandler expressionHandler,
|
|
MethodSecurityExpressionHandler expressionHandler,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
ObjectProvider<PrePostTemplateDefaults> defaultsObjectProvider,
|
|
ObjectProvider<ObservationRegistry> registryProvider) {
|
|
ObjectProvider<ObservationRegistry> registryProvider) {
|
|
PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
|
|
PostAuthorizeReactiveAuthorizationManager manager = new PostAuthorizeReactiveAuthorizationManager(
|
|
expressionHandler);
|
|
expressionHandler);
|
|
ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(manager, registryProvider);
|
|
ReactiveAuthorizationManager<MethodInvocationResult> authorizationManager = manager(manager, registryProvider);
|
|
- defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults);
|
|
|
|
- return AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize(authorizationManager);
|
|
|
|
|
|
+ AuthorizationAdvisor interceptor = AuthorizationManagerAfterReactiveMethodInterceptor
|
|
|
|
+ .postAuthorize(authorizationManager);
|
|
|
|
+ return new DeferringMethodInterceptor<>(interceptor,
|
|
|
|
+ (i) -> defaultsObjectProvider.ifAvailable(manager::setTemplateDefaults));
|
|
}
|
|
}
|
|
|
|
|
|
@Bean
|
|
@Bean
|
|
@@ -112,4 +125,50 @@ final class ReactiveAuthorizationManagerMethodSecurityConfiguration {
|
|
return new DeferringObservationReactiveAuthorizationManager<>(registryProvider, delegate);
|
|
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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|