Skip to content

Commit bade66e

Browse files
committed
Fix Circular Dependency
Closes gh-14674
1 parent 07ac0b6 commit bade66e

File tree

1 file changed

+59
-45
lines changed

1 file changed

+59
-45
lines changed

config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

+59-45
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,28 @@
1616

1717
package org.springframework.security.config.annotation.method.configuration;
1818

19+
import java.util.function.Consumer;
1920
import java.util.function.Supplier;
2021

2122
import io.micrometer.observation.ObservationRegistry;
23+
import org.aopalliance.aop.Advice;
2224
import org.aopalliance.intercept.MethodInterceptor;
2325
import org.aopalliance.intercept.MethodInvocation;
26+
import org.jetbrains.annotations.NotNull;
27+
import org.jetbrains.annotations.Nullable;
2428

29+
import org.springframework.aop.Pointcut;
30+
import org.springframework.aop.PointcutAdvisor;
31+
import org.springframework.aop.framework.AopInfrastructureBean;
2532
import org.springframework.beans.factory.ObjectProvider;
2633
import org.springframework.beans.factory.config.BeanDefinition;
2734
import org.springframework.context.ApplicationContext;
2835
import org.springframework.context.annotation.Bean;
2936
import org.springframework.context.annotation.Configuration;
3037
import org.springframework.context.annotation.ImportAware;
3138
import org.springframework.context.annotation.Role;
39+
import org.springframework.core.Ordered;
3240
import org.springframework.core.type.AnnotationMetadata;
33-
import org.springframework.expression.EvaluationContext;
34-
import org.springframework.expression.Expression;
35-
import org.springframework.expression.ExpressionParser;
3641
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
3742
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
3843
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
@@ -47,7 +52,6 @@
4752
import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
4853
import org.springframework.security.authorization.method.PrePostTemplateDefaults;
4954
import org.springframework.security.config.core.GrantedAuthorityDefaults;
50-
import org.springframework.security.core.Authentication;
5155
import org.springframework.security.core.context.SecurityContextHolderStrategy;
5256
import org.springframework.util.function.SingletonSupplier;
5357

@@ -76,11 +80,12 @@ static MethodInterceptor preFilterAuthorizationMethodInterceptor(
7680
ApplicationContext context) {
7781
PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
7882
preFilter.setOrder(preFilter.getOrder() + configuration.interceptorOrderOffset);
79-
strategyProvider.ifAvailable(preFilter::setSecurityContextHolderStrategy);
80-
methodSecurityDefaultsProvider.ifAvailable(preFilter::setTemplateDefaults);
81-
preFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
82-
defaultsProvider, roleHierarchyProvider, context));
83-
return preFilter;
83+
return new DeferringMethodInterceptor<>(preFilter, (f) -> {
84+
methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
85+
f.setExpressionHandler(expressionHandlerProvider
86+
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
87+
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
88+
});
8489
}
8590

8691
@Bean
@@ -94,15 +99,16 @@ static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
9499
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
95100
PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
96101
PreAuthorizeAuthorizationManager manager = new PreAuthorizeAuthorizationManager();
97-
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
98-
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
99-
defaultsProvider, roleHierarchyProvider, context));
100102
AuthorizationManagerBeforeMethodInterceptor preAuthorize = AuthorizationManagerBeforeMethodInterceptor
101103
.preAuthorize(manager(manager, registryProvider));
102104
preAuthorize.setOrder(preAuthorize.getOrder() + configuration.interceptorOrderOffset);
103-
strategyProvider.ifAvailable(preAuthorize::setSecurityContextHolderStrategy);
104-
eventPublisherProvider.ifAvailable(preAuthorize::setAuthorizationEventPublisher);
105-
return preAuthorize;
105+
return new DeferringMethodInterceptor<>(preAuthorize, (f) -> {
106+
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
107+
manager.setExpressionHandler(expressionHandlerProvider
108+
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
109+
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
110+
eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
111+
});
106112
}
107113

108114
@Bean
@@ -116,15 +122,16 @@ static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
116122
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
117123
PrePostMethodSecurityConfiguration configuration, ApplicationContext context) {
118124
PostAuthorizeAuthorizationManager manager = new PostAuthorizeAuthorizationManager();
119-
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
120-
manager.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
121-
defaultsProvider, roleHierarchyProvider, context));
122125
AuthorizationManagerAfterMethodInterceptor postAuthorize = AuthorizationManagerAfterMethodInterceptor
123126
.postAuthorize(manager(manager, registryProvider));
124127
postAuthorize.setOrder(postAuthorize.getOrder() + configuration.interceptorOrderOffset);
125-
strategyProvider.ifAvailable(postAuthorize::setSecurityContextHolderStrategy);
126-
eventPublisherProvider.ifAvailable(postAuthorize::setAuthorizationEventPublisher);
127-
return postAuthorize;
128+
return new DeferringMethodInterceptor<>(postAuthorize, (f) -> {
129+
methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
130+
manager.setExpressionHandler(expressionHandlerProvider
131+
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
132+
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
133+
eventPublisherProvider.ifAvailable(f::setAuthorizationEventPublisher);
134+
});
128135
}
129136

130137
@Bean
@@ -138,11 +145,12 @@ static MethodInterceptor postFilterAuthorizationMethodInterceptor(
138145
ApplicationContext context) {
139146
PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
140147
postFilter.setOrder(postFilter.getOrder() + configuration.interceptorOrderOffset);
141-
strategyProvider.ifAvailable(postFilter::setSecurityContextHolderStrategy);
142-
methodSecurityDefaultsProvider.ifAvailable(postFilter::setTemplateDefaults);
143-
postFilter.setExpressionHandler(new DeferringMethodSecurityExpressionHandler(expressionHandlerProvider,
144-
defaultsProvider, roleHierarchyProvider, context));
145-
return postFilter;
148+
return new DeferringMethodInterceptor<>(postFilter, (f) -> {
149+
methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
150+
f.setExpressionHandler(expressionHandlerProvider
151+
.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
152+
strategyProvider.ifAvailable(f::setSecurityContextHolderStrategy);
153+
});
146154
}
147155

148156
private static MethodSecurityExpressionHandler defaultExpressionHandler(
@@ -167,42 +175,48 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
167175
this.interceptorOrderOffset = annotation.offset();
168176
}
169177

170-
private static final class DeferringMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
178+
private static final class DeferringMethodInterceptor<M extends Ordered & MethodInterceptor & PointcutAdvisor>
179+
implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
171180

172-
private final Supplier<MethodSecurityExpressionHandler> expressionHandler;
181+
private final Pointcut pointcut;
173182

174-
private DeferringMethodSecurityExpressionHandler(
175-
ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
176-
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
177-
ObjectProvider<RoleHierarchy> roleHierarchyProvider, ApplicationContext applicationContext) {
178-
this.expressionHandler = SingletonSupplier.of(() -> expressionHandlerProvider.getIfAvailable(
179-
() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, applicationContext)));
183+
private final int order;
184+
185+
private final Supplier<M> delegate;
186+
187+
DeferringMethodInterceptor(M delegate, Consumer<M> supplier) {
188+
this.pointcut = delegate.getPointcut();
189+
this.order = delegate.getOrder();
190+
this.delegate = SingletonSupplier.of(() -> {
191+
supplier.accept(delegate);
192+
return delegate;
193+
});
180194
}
181195

196+
@Nullable
182197
@Override
183-
public ExpressionParser getExpressionParser() {
184-
return this.expressionHandler.get().getExpressionParser();
198+
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
199+
return this.delegate.get().invoke(invocation);
185200
}
186201

187202
@Override
188-
public EvaluationContext createEvaluationContext(Authentication authentication, MethodInvocation invocation) {
189-
return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
203+
public Pointcut getPointcut() {
204+
return this.pointcut;
190205
}
191206

192207
@Override
193-
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication,
194-
MethodInvocation invocation) {
195-
return this.expressionHandler.get().createEvaluationContext(authentication, invocation);
208+
public Advice getAdvice() {
209+
return this;
196210
}
197211

198212
@Override
199-
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
200-
return this.expressionHandler.get().filter(filterTarget, filterExpression, ctx);
213+
public int getOrder() {
214+
return this.order;
201215
}
202216

203217
@Override
204-
public void setReturnObject(Object returnObject, EvaluationContext ctx) {
205-
this.expressionHandler.get().setReturnObject(returnObject, ctx);
218+
public boolean isPerInstance() {
219+
return true;
206220
}
207221

208222
}

0 commit comments

Comments
 (0)