浏览代码

Support Class Attributes in Annotation Template Processing

Closes gh-15721
DingHao 11 月之前
父节点
当前提交
5c20505b0e

+ 30 - 0
config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java

@@ -998,6 +998,15 @@ public class PrePostMethodSecurityConfigurationTests {
 		verify(expressionHandler, times(4)).createEvaluationContext(any(Supplier.class), any());
 	}
 
+	// gh-15721
+	@Test
+	@WithMockUser(roles = "uid")
+	public void methodWhenMetaAnnotationPropertiesHasClassProperties() {
+		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
+		assertThat(service.getIdPath("uid")).isEqualTo("uid");
+	}
+
 	private static Consumer<ConfigurableWebApplicationContext> disallowBeanOverriding() {
 		return (context) -> ((AnnotationConfigWebApplicationContext) context).setAllowBeanDefinitionOverriding(false);
 	}
@@ -1376,6 +1385,27 @@ public class PrePostMethodSecurityConfigurationTests {
 			return list;
 		}
 
+		@RestrictedAccess(entityClass = EntityClass.class)
+		String getIdPath(String id) {
+			return id;
+		}
+
+	}
+
+	@Retention(RetentionPolicy.RUNTIME)
+	@PreAuthorize("hasRole({idPath})")
+	@interface RestrictedAccess {
+
+		String idPath() default "#id";
+
+		Class<?> entityClass();
+
+		String[] recipes() default {};
+
+	}
+
+	static class EntityClass {
+
 	}
 
 	@Retention(RetentionPolicy.RUNTIME)

+ 25 - 1
core/src/main/java/org/springframework/security/authorization/method/AuthorizationAnnotationUtils.java

@@ -19,9 +19,11 @@ package org.springframework.security.authorization.method;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 
 import org.springframework.core.annotation.AnnotationConfigurationException;
@@ -29,6 +31,8 @@ import org.springframework.core.annotation.MergedAnnotation;
 import org.springframework.core.annotation.MergedAnnotations;
 import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
 import org.springframework.core.annotation.RepeatableContainers;
+import org.springframework.core.convert.TypeDescriptor;
+import org.springframework.core.convert.converter.GenericConverter;
 import org.springframework.core.convert.support.DefaultConversionService;
 import org.springframework.util.PropertyPlaceholderHelper;
 
@@ -55,6 +59,12 @@ import org.springframework.util.PropertyPlaceholderHelper;
  */
 final class AuthorizationAnnotationUtils {
 
+	private static final DefaultConversionService conversionService = new DefaultConversionService();
+
+	static {
+		conversionService.addConverter(new ClassToStringConverter());
+	}
+
 	static <A extends Annotation> Function<AnnotatedElement, A> withDefaults(Class<A> type,
 			PrePostTemplateDefaults defaults) {
 		Function<MergedAnnotation<A>, A> map = (mergedAnnotation) -> {
@@ -70,7 +80,7 @@ final class AuthorizationAnnotationUtils {
 				String key = property.getKey();
 				Object value = property.getValue();
 				String asString = (value instanceof String) ? (String) value
-						: DefaultConversionService.getSharedInstance().convert(value, String.class);
+						: conversionService.convert(value, String.class);
 				stringProperties.put(key, asString);
 			}
 			AnnotatedElement annotatedElement = (AnnotatedElement) mergedAnnotation.getSource();
@@ -156,4 +166,18 @@ final class AuthorizationAnnotationUtils {
 
 	}
 
+	static class ClassToStringConverter implements GenericConverter {
+
+		@Override
+		public Set<ConvertiblePair> getConvertibleTypes() {
+			return Collections.singleton(new ConvertiblePair(Class.class, String.class));
+		}
+
+		@Override
+		public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
+			return (source != null) ? source.toString() : null;
+		}
+
+	}
+
 }