Skip to content

Commit 27af1df

Browse files
committed
Simplify Method Interceptor Configuration
Simplifies to use only one ObjectProvider for easier future maintenance Issue gh-15592
1 parent 2403657 commit 27af1df

File tree

4 files changed

+278
-193
lines changed

4 files changed

+278
-193
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.config.annotation.method.configuration;
18+
19+
import java.util.function.Supplier;
20+
21+
import org.aopalliance.aop.Advice;
22+
import org.aopalliance.intercept.MethodInvocation;
23+
import org.jetbrains.annotations.NotNull;
24+
import org.jetbrains.annotations.Nullable;
25+
26+
import org.springframework.aop.Pointcut;
27+
import org.springframework.security.authorization.method.AuthorizationAdvisor;
28+
import org.springframework.util.function.SingletonSupplier;
29+
30+
final class DeferringMethodInterceptor<M extends AuthorizationAdvisor> implements AuthorizationAdvisor {
31+
32+
private final Pointcut pointcut;
33+
34+
private final Supplier<M> delegate;
35+
36+
DeferringMethodInterceptor(Pointcut pointcut, Supplier<M> delegate) {
37+
this.pointcut = pointcut;
38+
this.delegate = SingletonSupplier.of(delegate);
39+
}
40+
41+
@Nullable
42+
@Override
43+
public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
44+
return this.delegate.get().invoke(invocation);
45+
}
46+
47+
@Override
48+
public Pointcut getPointcut() {
49+
return this.pointcut;
50+
}
51+
52+
@Override
53+
public Advice getAdvice() {
54+
return this;
55+
}
56+
57+
@Override
58+
public int getOrder() {
59+
return this.delegate.get().getOrder();
60+
}
61+
62+
@Override
63+
public boolean isPerInstance() {
64+
return true;
65+
}
66+
67+
}

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

+51-26
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,30 @@
1616

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

19+
import java.util.function.Supplier;
20+
1921
import io.micrometer.observation.ObservationRegistry;
2022
import org.aopalliance.intercept.MethodInterceptor;
2123
import org.aopalliance.intercept.MethodInvocation;
2224

25+
import org.springframework.aop.Pointcut;
2326
import org.springframework.aop.framework.AopInfrastructureBean;
2427
import org.springframework.beans.factory.ObjectProvider;
28+
import org.springframework.beans.factory.annotation.Autowired;
2529
import org.springframework.beans.factory.config.BeanDefinition;
2630
import org.springframework.context.annotation.Bean;
2731
import org.springframework.context.annotation.Configuration;
2832
import org.springframework.context.annotation.ImportAware;
2933
import org.springframework.context.annotation.Role;
3034
import org.springframework.core.type.AnnotationMetadata;
31-
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
3235
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
3336
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
3437
import org.springframework.security.authorization.AuthorizationEventPublisher;
3538
import org.springframework.security.authorization.AuthorizationManager;
39+
import org.springframework.security.authorization.ObservationAuthorizationManager;
3640
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
3741
import org.springframework.security.authorization.method.Jsr250AuthorizationManager;
3842
import org.springframework.security.config.core.GrantedAuthorityDefaults;
39-
import org.springframework.security.core.context.SecurityContextHolder;
4043
import org.springframework.security.core.context.SecurityContextHolderStrategy;
4144

4245
/**
@@ -47,42 +50,64 @@
4750
* @since 5.6
4851
* @see EnableMethodSecurity
4952
*/
50-
@Configuration(proxyBeanMethods = false)
53+
@Configuration(value = "_jsr250MethodSecurityConfiguration", proxyBeanMethods = false)
5154
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
5255
final class Jsr250MethodSecurityConfiguration implements ImportAware, AopInfrastructureBean {
5356

54-
private int interceptorOrderOffset;
57+
private static final Pointcut pointcut = AuthorizationManagerBeforeMethodInterceptor.jsr250().getPointcut();
58+
59+
private final Jsr250AuthorizationManager authorizationManager = new Jsr250AuthorizationManager();
60+
61+
private AuthorizationManagerBeforeMethodInterceptor methodInterceptor = AuthorizationManagerBeforeMethodInterceptor
62+
.jsr250(this.authorizationManager);
5563

5664
@Bean
5765
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
5866
static MethodInterceptor jsr250AuthorizationMethodInterceptor(
59-
ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
60-
ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
61-
ObjectProvider<AuthorizationEventPublisher> eventPublisherProvider,
62-
ObjectProvider<ObservationRegistry> registryProvider, ObjectProvider<RoleHierarchy> roleHierarchyProvider,
63-
Jsr250MethodSecurityConfiguration configuration) {
64-
Jsr250AuthorizationManager jsr250 = new Jsr250AuthorizationManager();
65-
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
66-
RoleHierarchy roleHierarchy = roleHierarchyProvider.getIfAvailable(NullRoleHierarchy::new);
67-
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
68-
jsr250.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
69-
defaultsProvider.ifAvailable((d) -> jsr250.setRolePrefix(d.getRolePrefix()));
70-
SecurityContextHolderStrategy strategy = strategyProvider
71-
.getIfAvailable(SecurityContextHolder::getContextHolderStrategy);
72-
AuthorizationManager<MethodInvocation> manager = new DeferringObservationAuthorizationManager<>(
73-
registryProvider, jsr250);
74-
AuthorizationManagerBeforeMethodInterceptor interceptor = AuthorizationManagerBeforeMethodInterceptor
75-
.jsr250(manager);
76-
interceptor.setOrder(interceptor.getOrder() + configuration.interceptorOrderOffset);
77-
interceptor.setSecurityContextHolderStrategy(strategy);
78-
eventPublisherProvider.ifAvailable(interceptor::setAuthorizationEventPublisher);
79-
return interceptor;
67+
ObjectProvider<Jsr250MethodSecurityConfiguration> _jsr250MethodSecurityConfiguration) {
68+
Supplier<AuthorizationManagerBeforeMethodInterceptor> supplier = () -> {
69+
Jsr250MethodSecurityConfiguration configuration = _jsr250MethodSecurityConfiguration.getObject();
70+
return configuration.methodInterceptor;
71+
};
72+
return new DeferringMethodInterceptor<>(pointcut, supplier);
8073
}
8174

8275
@Override
8376
public void setImportMetadata(AnnotationMetadata importMetadata) {
8477
EnableMethodSecurity annotation = importMetadata.getAnnotations().get(EnableMethodSecurity.class).synthesize();
85-
this.interceptorOrderOffset = annotation.offset();
78+
this.methodInterceptor.setOrder(this.methodInterceptor.getOrder() + annotation.offset());
79+
}
80+
81+
@Autowired(required = false)
82+
void setGrantedAuthorityDefaults(GrantedAuthorityDefaults defaults) {
83+
this.authorizationManager.setRolePrefix(defaults.getRolePrefix());
84+
}
85+
86+
@Autowired(required = false)
87+
void setRoleHierarchy(RoleHierarchy roleHierarchy) {
88+
AuthoritiesAuthorizationManager authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
89+
authoritiesAuthorizationManager.setRoleHierarchy(roleHierarchy);
90+
this.authorizationManager.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
91+
}
92+
93+
@Autowired(required = false)
94+
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
95+
this.methodInterceptor.setSecurityContextHolderStrategy(securityContextHolderStrategy);
96+
}
97+
98+
@Autowired(required = false)
99+
void setObservationRegistry(ObservationRegistry registry) {
100+
if (registry.isNoop()) {
101+
return;
102+
}
103+
AuthorizationManager<MethodInvocation> observed = new ObservationAuthorizationManager<>(registry,
104+
this.authorizationManager);
105+
this.methodInterceptor = AuthorizationManagerBeforeMethodInterceptor.secured(observed);
106+
}
107+
108+
@Autowired(required = false)
109+
void setEventPublisher(AuthorizationEventPublisher eventPublisher) {
110+
this.methodInterceptor.setAuthorizationEventPublisher(eventPublisher);
86111
}
87112

88113
}

0 commit comments

Comments
 (0)