mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-23 10:48:51 +00:00
Add ExpressionTemplateValueProvider
Closes gh-17447 Signed-off-by: Mike Heath <michael.heath@familysearch.org>
This commit is contained in:
parent
dfc8be0d48
commit
93cb01612b
@ -59,13 +59,18 @@ import org.springframework.util.PropertyPlaceholderHelper;
|
|||||||
* {@code @HasRole} annotation found on a given {@link AnnotatedElement}.
|
* {@code @HasRole} annotation found on a given {@link AnnotatedElement}.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
|
* Meta-annotations that use enum values can use {@link ExpressionTemplateValueProvider} to
|
||||||
|
* provide custom placeholder values.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
* Since the process of synthesis is expensive, it is recommended to cache the synthesized
|
* Since the process of synthesis is expensive, it is recommended to cache the synthesized
|
||||||
* result to prevent multiple computations.
|
* result to prevent multiple computations.
|
||||||
*
|
*
|
||||||
* @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
|
* @author DingHao
|
||||||
* @since 6.4
|
* @author Mike Heath
|
||||||
|
* @since 7.0
|
||||||
*/
|
*/
|
||||||
final class ExpressionTemplateSecurityAnnotationScanner<A extends Annotation>
|
final class ExpressionTemplateSecurityAnnotationScanner<A extends Annotation>
|
||||||
extends AbstractSecurityAnnotationScanner<A> {
|
extends AbstractSecurityAnnotationScanner<A> {
|
||||||
@ -74,6 +79,7 @@ final class ExpressionTemplateSecurityAnnotationScanner<A extends Annotation>
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
conversionService.addConverter(new ClassToStringConverter());
|
conversionService.addConverter(new ClassToStringConverter());
|
||||||
|
conversionService.addConverter(new ExpressionTemplateValueProviderConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Class<A> type;
|
private final Class<A> type;
|
||||||
@ -162,4 +168,18 @@ final class ExpressionTemplateSecurityAnnotationScanner<A extends Annotation>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ExpressionTemplateValueProviderConverter implements GenericConverter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||||
|
return Collections.singleton(new ConvertiblePair(ExpressionTemplateValueProvider.class, String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
|
return (source != null) ? ((ExpressionTemplateValueProvider)source).getExpressionTemplateValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package org.springframework.security.core.annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a mechanism for providing custom values from enum types used in security
|
||||||
|
* meta-annotation expressions. For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* enum Permission implements ExpressionTemplateValueProvider {
|
||||||
|
* READ,
|
||||||
|
* WRITE;
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* public String getExpressionTemplateValue() {
|
||||||
|
* return switch (this) {
|
||||||
|
* case READ -> "user.permission-read";
|
||||||
|
* case WRITE -> "user.permission-write";
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @since 6.5
|
||||||
|
* @author Mike Heath
|
||||||
|
*/
|
||||||
|
public interface ExpressionTemplateValueProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to be used in an expression template.
|
||||||
|
*
|
||||||
|
* @return the value to be used in an expression template
|
||||||
|
*/
|
||||||
|
String getExpressionTemplateValue();
|
||||||
|
|
||||||
|
}
|
@ -54,6 +54,43 @@ public class ExpressionTemplateSecurityAnnotationScannerTests {
|
|||||||
assertThat(preAuthorize.value()).isEqualTo("check(#name)");
|
assertThat(preAuthorize.value()).isEqualTo("check(#name)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseMetaSourceAnnotationWithEnumImplementingExpressionTemplateValueProvider() throws Exception {
|
||||||
|
Method method = MessageService.class.getDeclaredMethod("process");
|
||||||
|
PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
|
||||||
|
assertThat(preAuthorize.value()).isEqualTo("hasAnyAuthority('user.READ','user.WRITE')");
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Permission implements ExpressionTemplateValueProvider {
|
||||||
|
READ,
|
||||||
|
WRITE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpressionTemplateValue() {
|
||||||
|
return switch (this) {
|
||||||
|
case READ -> "'user.READ'";
|
||||||
|
case WRITE -> "'user.WRITE'";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@PreAuthorize("hasAnyAuthority({permissions})")
|
||||||
|
@interface HasAnyCustomPermissions {
|
||||||
|
|
||||||
|
Permission[] permissions();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
@HasAnyCustomPermissions(permissions = { Permission.READ, Permission.WRITE })
|
||||||
|
@interface HasAllCustomPermissions {
|
||||||
|
}
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
@ -86,6 +123,9 @@ public class ExpressionTemplateSecurityAnnotationScannerTests {
|
|||||||
|
|
||||||
private interface MessageService {
|
private interface MessageService {
|
||||||
|
|
||||||
|
@HasAllCustomPermissions
|
||||||
|
void process();
|
||||||
|
|
||||||
@HasReadPermission("#name")
|
@HasReadPermission("#name")
|
||||||
String sayHello(String name);
|
String sayHello(String name);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user