From 96697472459f51cfb9be5f0557a78cfb5e10eed4 Mon Sep 17 00:00:00 2001 From: Florian Cramer Date: Wed, 10 May 2023 00:25:31 +0200 Subject: [PATCH] Ignore synthetic methods when checking for duplicate annotations Closes gh-13132 --- .../method/AuthorizationAnnotationUtils.java | 13 +++++++ .../AuthorizationAnnotationUtilsTests.java | 39 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 core/src/test/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtilsTests.java diff --git a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtils.java b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtils.java index 582436ba17..70eabb2efc 100644 --- a/core/src/main/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtils.java +++ b/core/src/main/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtils.java @@ -17,6 +17,7 @@ package org.springframework.security.authorization.method; import java.lang.annotation.Annotation; +import java.lang.reflect.Executable; import java.lang.reflect.Method; import org.springframework.core.annotation.AnnotationConfigurationException; @@ -96,6 +97,10 @@ final class AuthorizationAnnotationUtils { Class annotationType) { boolean alreadyFound = false; for (MergedAnnotation mergedAnnotation : mergedAnnotations) { + if (isSynthetic(mergedAnnotation.getSource())) { + continue; + } + if (mergedAnnotation.getType() == annotationType) { if (alreadyFound) { return true; @@ -106,6 +111,14 @@ final class AuthorizationAnnotationUtils { return false; } + private static boolean isSynthetic(Object object) { + if (object instanceof Executable) { + return ((Executable) object).isSynthetic(); + } + + return false; + } + private AuthorizationAnnotationUtils() { } diff --git a/core/src/test/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtilsTests.java b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtilsTests.java new file mode 100644 index 0000000000..480c2860ec --- /dev/null +++ b/core/src/test/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtilsTests.java @@ -0,0 +1,39 @@ +package org.springframework.security.authorization.method; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.security.access.prepost.PreAuthorize; + +import static org.assertj.core.api.Assertions.assertThatNoException; + +/** + * Tests for {@link AuthorizationAnnotationUtils} + */ +class AuthorizationAnnotationUtilsTests { + + @Test // gh-13132 + public void annotationsOnSyntheticMethodsShouldNotTriggerAnnotationConfigurationException() + throws NoSuchMethodException { + StringRepository proxy = + (StringRepository) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[] {StringRepository.class}, (p, m, args) -> null); + Method method = proxy.getClass().getDeclaredMethod("findAll"); + assertThatNoException() + .isThrownBy(() -> AuthorizationAnnotationUtils.findUniqueAnnotation(method, PreAuthorize.class)); + } + + private interface BaseRepository { + + Iterable findAll(); + } + + private interface StringRepository extends BaseRepository { + + @Override + @PreAuthorize("hasRole('someRole')") + List findAll(); + } +}