|
@@ -18,6 +18,7 @@ package org.springframework.security.core.annotation;
|
|
|
|
|
|
import java.lang.annotation.Annotation;
|
|
import java.lang.annotation.Annotation;
|
|
import java.lang.reflect.AnnotatedElement;
|
|
import java.lang.reflect.AnnotatedElement;
|
|
|
|
+import java.lang.reflect.Executable;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Parameter;
|
|
import java.lang.reflect.Parameter;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
@@ -83,6 +84,7 @@ import org.springframework.util.ClassUtils;
|
|
*
|
|
*
|
|
* @param <A> the annotation to search for and synthesize
|
|
* @param <A> the annotation to search for and synthesize
|
|
* @author Josh Cummings
|
|
* @author Josh Cummings
|
|
|
|
+ * @author DingHao
|
|
* @since 6.4
|
|
* @since 6.4
|
|
*/
|
|
*/
|
|
final class UniqueSecurityAnnotationScanner<A extends Annotation> extends AbstractSecurityAnnotationScanner<A> {
|
|
final class UniqueSecurityAnnotationScanner<A extends Annotation> extends AbstractSecurityAnnotationScanner<A> {
|
|
@@ -107,7 +109,7 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
|
MergedAnnotation<A> merge(AnnotatedElement element, Class<?> targetClass) {
|
|
MergedAnnotation<A> merge(AnnotatedElement element, Class<?> targetClass) {
|
|
if (element instanceof Parameter parameter) {
|
|
if (element instanceof Parameter parameter) {
|
|
return this.uniqueParameterAnnotationCache.computeIfAbsent(parameter, (p) -> {
|
|
return this.uniqueParameterAnnotationCache.computeIfAbsent(parameter, (p) -> {
|
|
- List<MergedAnnotation<A>> annotations = findDirectAnnotations(p);
|
|
|
|
|
|
+ List<MergedAnnotation<A>> annotations = findParameterAnnotations(p);
|
|
return requireUnique(p, annotations);
|
|
return requireUnique(p, annotations);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
@@ -137,6 +139,56 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private List<MergedAnnotation<A>> findParameterAnnotations(Parameter current) {
|
|
|
|
+ List<MergedAnnotation<A>> directAnnotations = findDirectAnnotations(current);
|
|
|
|
+ if (!directAnnotations.isEmpty()) {
|
|
|
|
+ return directAnnotations;
|
|
|
|
+ }
|
|
|
|
+ Executable executable = current.getDeclaringExecutable();
|
|
|
|
+ if (executable instanceof Method method) {
|
|
|
|
+ Class<?> clazz = method.getDeclaringClass();
|
|
|
|
+ Set<Class<?>> visited = new HashSet<>();
|
|
|
|
+ while (clazz != null && clazz != Object.class) {
|
|
|
|
+ directAnnotations = findClosestParameterAnnotations(method, clazz, current, visited);
|
|
|
|
+ if (!directAnnotations.isEmpty()) {
|
|
|
|
+ return directAnnotations;
|
|
|
|
+ }
|
|
|
|
+ clazz = clazz.getSuperclass();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private List<MergedAnnotation<A>> findClosestParameterAnnotations(Method method, Class<?> clazz, Parameter current,
|
|
|
|
+ Set<Class<?>> visited) {
|
|
|
|
+ if (!visited.add(clazz)) {
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
+ }
|
|
|
|
+ List<MergedAnnotation<A>> annotations = new ArrayList<>(findDirectParameterAnnotations(method, clazz, current));
|
|
|
|
+ for (Class<?> ifc : clazz.getInterfaces()) {
|
|
|
|
+ annotations.addAll(findClosestParameterAnnotations(method, ifc, current, visited));
|
|
|
|
+ }
|
|
|
|
+ return annotations;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private List<MergedAnnotation<A>> findDirectParameterAnnotations(Method method, Class<?> clazz, Parameter current) {
|
|
|
|
+ try {
|
|
|
|
+ Method methodToUse = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
|
|
|
+ for (Parameter parameter : methodToUse.getParameters()) {
|
|
|
|
+ if (parameter.getName().equals(current.getName())) {
|
|
|
|
+ List<MergedAnnotation<A>> directAnnotations = findDirectAnnotations(parameter);
|
|
|
|
+ if (!directAnnotations.isEmpty()) {
|
|
|
|
+ return directAnnotations;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ catch (NoSuchMethodException ex) {
|
|
|
|
+ // move on
|
|
|
|
+ }
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
+ }
|
|
|
|
+
|
|
private List<MergedAnnotation<A>> findMethodAnnotations(Method method, Class<?> targetClass) {
|
|
private List<MergedAnnotation<A>> findMethodAnnotations(Method method, Class<?> targetClass) {
|
|
// The method may be on an interface, but we need attributes from the target
|
|
// The method may be on an interface, but we need attributes from the target
|
|
// class.
|
|
// class.
|