Invert AuthorizeReturnObjectMethodInterceptor Dependency

Closes gh-16922
This commit is contained in:
Josh Cummings 2025-04-10 08:37:00 -06:00
parent 1ca33cae70
commit 5841e35cae
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
3 changed files with 41 additions and 16 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.security.config.annotation.method.configuration; package org.springframework.security.config.annotation.method.configuration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
@ -40,21 +41,19 @@ final class AuthorizationProxyConfiguration implements AopInfrastructureBean {
@Bean @Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static AuthorizationAdvisorProxyFactory authorizationProxyFactory( static AuthorizationAdvisorProxyFactory authorizationProxyFactory(
ObjectProvider<AuthorizationAdvisor> authorizationAdvisors,
ObjectProvider<Customizer<AuthorizationAdvisorProxyFactory>> customizers) { ObjectProvider<Customizer<AuthorizationAdvisorProxyFactory>> customizers) {
AuthorizationAdvisorProxyFactory factory = new AuthorizationAdvisorProxyFactory(new ArrayList<>()); List<AuthorizationAdvisor> advisors = new ArrayList<>();
authorizationAdvisors.forEach(advisors::add);
AuthorizationAdvisorProxyFactory factory = new AuthorizationAdvisorProxyFactory(advisors);
customizers.forEach((c) -> c.customize(factory)); customizers.forEach((c) -> c.customize(factory));
return factory; return factory;
} }
@Bean @Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static MethodInterceptor authorizeReturnObjectMethodInterceptor(ObjectProvider<AuthorizationAdvisor> provider, static MethodInterceptor authorizeReturnObjectMethodInterceptor() {
AuthorizationAdvisorProxyFactory authorizationProxyFactory) { return new AuthorizeReturnObjectMethodInterceptor();
provider.forEach(authorizationProxyFactory::addAdvisor);
AuthorizeReturnObjectMethodInterceptor interceptor = new AuthorizeReturnObjectMethodInterceptor(
authorizationProxyFactory);
authorizationProxyFactory.addAdvisor(interceptor);
return interceptor;
} }
@Bean @Bean

View File

@ -100,16 +100,16 @@ public final class AuthorizationAdvisorProxyFactory implements AuthorizationProx
/** /**
* Construct an {@link AuthorizationAdvisorProxyFactory} with the provided advisors. * Construct an {@link AuthorizationAdvisorProxyFactory} with the provided advisors.
*
* <p>
* The list may be empty, in the case where advisors are added later using
* {@link #addAdvisor}.
* @param advisors the advisors to use * @param advisors the advisors to use
* @since 6.4 * @since 6.4
*/ */
public AuthorizationAdvisorProxyFactory(List<AuthorizationAdvisor> advisors) { public AuthorizationAdvisorProxyFactory(List<AuthorizationAdvisor> advisors) {
this.advisors = new ArrayList<>(advisors); this.advisors = new ArrayList<>(advisors);
AnnotationAwareOrderComparator.sort(this.advisors); for (AuthorizationAdvisor advisor : this.advisors) {
if (advisor instanceof AuthorizeReturnObjectMethodInterceptor interceptor) {
interceptor.setAuthorizationProxyFactory(this);
}
}
} }
/** /**
@ -124,8 +124,8 @@ public final class AuthorizationAdvisorProxyFactory implements AuthorizationProx
advisors.add(AuthorizationManagerAfterMethodInterceptor.postAuthorize()); advisors.add(AuthorizationManagerAfterMethodInterceptor.postAuthorize());
advisors.add(new PreFilterAuthorizationMethodInterceptor()); advisors.add(new PreFilterAuthorizationMethodInterceptor());
advisors.add(new PostFilterAuthorizationMethodInterceptor()); advisors.add(new PostFilterAuthorizationMethodInterceptor());
advisors.add(new AuthorizeReturnObjectMethodInterceptor());
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors); AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
AnnotationAwareOrderComparator.sort(proxyFactory.advisors); AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
return proxyFactory; return proxyFactory;
} }
@ -142,8 +142,8 @@ public final class AuthorizationAdvisorProxyFactory implements AuthorizationProx
advisors.add(AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize()); advisors.add(AuthorizationManagerAfterReactiveMethodInterceptor.postAuthorize());
advisors.add(new PreFilterAuthorizationReactiveMethodInterceptor()); advisors.add(new PreFilterAuthorizationReactiveMethodInterceptor());
advisors.add(new PostFilterAuthorizationReactiveMethodInterceptor()); advisors.add(new PostFilterAuthorizationReactiveMethodInterceptor());
advisors.add(new AuthorizeReturnObjectMethodInterceptor());
AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors); AuthorizationAdvisorProxyFactory proxyFactory = new AuthorizationAdvisorProxyFactory(advisors);
proxyFactory.addAdvisor(new AuthorizeReturnObjectMethodInterceptor(proxyFactory));
AnnotationAwareOrderComparator.sort(proxyFactory.advisors); AnnotationAwareOrderComparator.sort(proxyFactory.advisors);
return proxyFactory; return proxyFactory;
} }
@ -230,7 +230,9 @@ public final class AuthorizationAdvisorProxyFactory implements AuthorizationProx
* them. * them.
* @param advisor * @param advisor
* @since 6.4 * @since 6.4
* @deprecated please provide all advisors in the constructor
*/ */
@Deprecated
public void addAdvisor(AuthorizationAdvisor advisor) { public void addAdvisor(AuthorizationAdvisor advisor) {
this.advisors.add(advisor); this.advisors.add(advisor);
} }

View File

@ -39,7 +39,7 @@ import org.springframework.util.ClassUtils;
*/ */
public final class AuthorizeReturnObjectMethodInterceptor implements AuthorizationAdvisor { public final class AuthorizeReturnObjectMethodInterceptor implements AuthorizationAdvisor {
private final AuthorizationProxyFactory authorizationProxyFactory; private AuthorizationProxyFactory authorizationProxyFactory;
private Pointcut pointcut = Pointcuts.intersection( private Pointcut pointcut = Pointcuts.intersection(
new MethodReturnTypePointcut(Predicate.not(ClassUtils::isVoidType)), new MethodReturnTypePointcut(Predicate.not(ClassUtils::isVoidType)),
@ -47,6 +47,19 @@ public final class AuthorizeReturnObjectMethodInterceptor implements Authorizati
private int order = AuthorizationInterceptorsOrder.SECURE_RESULT.getOrder(); private int order = AuthorizationInterceptorsOrder.SECURE_RESULT.getOrder();
/**
* Construct the interceptor
*
* <p>
* Using this constructor requires you to specify
* {@link #setAuthorizationProxyFactory}
* </p>
* @since 6.5
*/
public AuthorizeReturnObjectMethodInterceptor() {
}
public AuthorizeReturnObjectMethodInterceptor(AuthorizationProxyFactory authorizationProxyFactory) { public AuthorizeReturnObjectMethodInterceptor(AuthorizationProxyFactory authorizationProxyFactory) {
Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null"); Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null");
this.authorizationProxyFactory = authorizationProxyFactory; this.authorizationProxyFactory = authorizationProxyFactory;
@ -58,9 +71,20 @@ public final class AuthorizeReturnObjectMethodInterceptor implements Authorizati
if (result == null) { if (result == null) {
return null; return null;
} }
Assert.notNull(this.authorizationProxyFactory, "authorizationProxyFactory cannot be null");
return this.authorizationProxyFactory.proxy(result); return this.authorizationProxyFactory.proxy(result);
} }
/**
* Use this {@link AuthorizationProxyFactory}
* @param authorizationProxyFactory the proxy factory to use
* @since 6.5
*/
public void setAuthorizationProxyFactory(AuthorizationProxyFactory authorizationProxyFactory) {
Assert.notNull(authorizationProxyFactory, "authorizationProxyFactory cannot be null");
this.authorizationProxyFactory = authorizationProxyFactory;
}
@Override @Override
public int getOrder() { public int getOrder() {
return this.order; return this.order;