From e5694ac7b5e4394b920c6cab48b7bfbd871f84bd Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 15 Sep 2025 09:16:50 -0600 Subject: [PATCH] Fallback to Object When Determining Overridden Methods Closes gh-17898 --- .../UniqueSecurityAnnotationScanner.java | 2 +- .../UniqueSecurityAnnotationScannerTests.java | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java b/core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java index 3a2576b276..2ea80d31fd 100644 --- a/core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java +++ b/core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java @@ -252,7 +252,7 @@ final class UniqueSecurityAnnotationScanner extends Abstra } for (int i = 0; i < rootParameterTypes.length; i++) { Class resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass) - .resolve(); + .toClass(); if (rootParameterTypes[i] != resolvedParameterType) { return false; } diff --git a/core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java b/core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java index 757e35a254..88d73ef053 100644 --- a/core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java +++ b/core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test; import org.springframework.core.annotation.AnnotationConfigurationException; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -275,6 +276,14 @@ public class UniqueSecurityAnnotationScannerTests { assertThat(pre).isNotNull(); } + // gh-17898 + @Test + void scanWhenAnnotationOnParameterizedUndeclaredMethodAndThenLocates() throws Exception { + Method method = ClassUtils.getMethod(GenericInterfaceImpl.class, "processOneAndTwo", Long.class, Object.class); + PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass()); + assertThat(pre).isNotNull(); + } + @PreAuthorize("one") private interface AnnotationOnInterface { @@ -637,4 +646,27 @@ public class UniqueSecurityAnnotationScannerTests { } + interface GenericInterface { + + @PreAuthorize("hasAuthority('thirtythree')") + void processOneAndTwo(A value1, B value2); + + } + + abstract static class GenericAbstractSuperclass implements GenericInterface { + + @Override + public void processOneAndTwo(Long value1, C value2) { + } + + } + + static class GenericInterfaceImpl extends GenericAbstractSuperclass { + + // The compiler does not require us to declare a concrete + // processOneAndTwo(Long, String) method, and we intentionally + // do not declare one here. + + } + }