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 d166c77fcb1..32bc8ea57da 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 @@ -149,14 +149,10 @@ private List> findParameterAnnotations(Parameter current) { } Executable executable = current.getDeclaringExecutable(); if (executable instanceof Method method) { - Class clazz = method.getDeclaringClass(); - Set> visited = new HashSet<>(); - while (clazz != null && clazz != Object.class) { - directAnnotations = findClosestParameterAnnotations(method, clazz, current, visited); - if (!directAnnotations.isEmpty()) { - return directAnnotations; - } - clazz = clazz.getSuperclass(); + directAnnotations = findClosestParameterAnnotations(method, method.getDeclaringClass(), current, + new HashSet<>()); + if (!directAnnotations.isEmpty()) { + return directAnnotations; } } return Collections.emptyList(); @@ -164,10 +160,15 @@ private List> findParameterAnnotations(Parameter current) { private List> findClosestParameterAnnotations(Method method, Class clazz, Parameter current, Set> visited) { - if (!visited.add(clazz)) { + if (clazz == null || clazz == Object.class || !visited.add(clazz)) { return Collections.emptyList(); } - List> annotations = new ArrayList<>(findDirectParameterAnnotations(method, clazz, current)); + List> directAnnotations = findDirectParameterAnnotations(method, clazz, current); + if (!directAnnotations.isEmpty()) { + return directAnnotations; + } + List> annotations = new ArrayList<>( + findClosestParameterAnnotations(method, clazz.getSuperclass(), current, visited)); for (Class ifc : clazz.getInterfaces()) { annotations.addAll(findClosestParameterAnnotations(method, ifc, current, visited)); } 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 d8189350f26..139d2203e11 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 @@ -319,6 +319,13 @@ void scanWhenAnnotationOnParameterizedMethodThenLocates() throws Exception { assertThat(pre).isNotNull(); } + @Test + void scanParameterAnnotationWhenPresentInParentAndInterfaceThenException() throws Exception { + Parameter parameter = DefaultUserService.class.getDeclaredMethod("batch", String[].class).getParameters()[0]; + assertThatExceptionOfType(AnnotationConfigurationException.class) + .isThrownBy(() -> this.parameterScanner.scan(parameter)); + } + interface UserService { void add(@CustomParameterAnnotation("one") String user); @@ -345,6 +352,8 @@ interface ThirdPartyUserService { interface RemoteUserService extends ThirdPartyUserService { + void batch(@CustomParameterAnnotation("six") String... user); + } static class UserServiceImpl implements UserService, OtherUserService, RemoteUserService { @@ -369,6 +378,20 @@ public void delete(String user) { } + @Override + public void batch(@CustomParameterAnnotation("seven") String... user) { + + } + + } + + static class DefaultUserService extends UserServiceImpl implements RemoteUserService { + + @Override + public void batch(String... user) { + + } + } @Target({ ElementType.PARAMETER })