Add meta-annotation parameter support
Closes gh-14480
This commit is contained in:
@@ -16,14 +16,20 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.core.MethodClassKey;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* For internal use only, as this contract is likely to change
|
||||
@@ -35,6 +41,10 @@ abstract class AbstractExpressionAttributeRegistry<T extends ExpressionAttribute
|
||||
|
||||
private final Map<MethodClassKey, T> cachedAttributes = new ConcurrentHashMap<>();
|
||||
|
||||
private MethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
|
||||
private PrePostTemplateDefaults defaults;
|
||||
|
||||
/**
|
||||
* Returns an {@link ExpressionAttribute} for the {@link MethodInvocation}.
|
||||
* @param mi the {@link MethodInvocation} to use
|
||||
@@ -58,6 +68,28 @@ abstract class AbstractExpressionAttributeRegistry<T extends ExpressionAttribute
|
||||
return this.cachedAttributes.computeIfAbsent(cacheKey, (k) -> resolveAttribute(method, targetClass));
|
||||
}
|
||||
|
||||
final <A extends Annotation> Function<AnnotatedElement, A> findUniqueAnnotation(Class<A> type) {
|
||||
return (this.defaults != null) ? AuthorizationAnnotationUtils.withDefaults(type, this.defaults)
|
||||
: AuthorizationAnnotationUtils.withDefaults(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MethodSecurityExpressionHandler}.
|
||||
* @return the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method to provide the non-null
|
||||
* {@link ExpressionAttribute} for the method and the target class.
|
||||
|
||||
@@ -19,13 +19,19 @@ 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.function.Function;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationConfigurationException;
|
||||
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.support.DefaultConversionService;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
|
||||
/**
|
||||
* A collection of utility methods that check for, and error on, conflicting annotations.
|
||||
@@ -50,6 +56,43 @@ import org.springframework.core.annotation.RepeatableContainers;
|
||||
*/
|
||||
final class AuthorizationAnnotationUtils {
|
||||
|
||||
static <A extends Annotation> Function<AnnotatedElement, A> withDefaults(Class<A> type,
|
||||
PrePostTemplateDefaults defaults) {
|
||||
Function<MergedAnnotation<A>, A> map = (mergedAnnotation) -> {
|
||||
if (mergedAnnotation.getMetaSource() == null) {
|
||||
return mergedAnnotation.synthesize();
|
||||
}
|
||||
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("{", "}", null,
|
||||
defaults.isIgnoreUnknown());
|
||||
String expression = (String) mergedAnnotation.asMap().get("value");
|
||||
Map<String, Object> annotationProperties = mergedAnnotation.getMetaSource().asMap();
|
||||
Map<String, String> stringProperties = new HashMap<>();
|
||||
for (Map.Entry<String, Object> property : annotationProperties.entrySet()) {
|
||||
String key = property.getKey();
|
||||
Object value = property.getValue();
|
||||
String asString = (value instanceof String) ? (String) value
|
||||
: DefaultConversionService.getSharedInstance().convert(value, String.class);
|
||||
stringProperties.put(key, asString);
|
||||
}
|
||||
AnnotatedElement annotatedElement = (AnnotatedElement) mergedAnnotation.getSource();
|
||||
String value = helper.replacePlaceholders(expression, stringProperties::get);
|
||||
return MergedAnnotation.of(annotatedElement, type, Collections.singletonMap("value", value)).synthesize();
|
||||
};
|
||||
return (annotatedElement) -> findDistinctAnnotation(annotatedElement, type, map);
|
||||
}
|
||||
|
||||
static <A extends Annotation> Function<AnnotatedElement, A> withDefaults(Class<A> type) {
|
||||
return (annotatedElement) -> findDistinctAnnotation(annotatedElement, type, MergedAnnotation::synthesize);
|
||||
}
|
||||
|
||||
static <A extends Annotation> A findUniqueAnnotation(Method method, Class<A> annotationType) {
|
||||
return findDistinctAnnotation(method, annotationType, MergedAnnotation::synthesize);
|
||||
}
|
||||
|
||||
static <A extends Annotation> A findUniqueAnnotation(Class<?> type, Class<A> annotationType) {
|
||||
return findDistinctAnnotation(type, annotationType, MergedAnnotation::synthesize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an exhaustive search on the type hierarchy of the given {@link Method} for
|
||||
* the annotation of type {@code annotationType}, including any annotations using
|
||||
@@ -64,8 +107,9 @@ final class AuthorizationAnnotationUtils {
|
||||
* @throws AnnotationConfigurationException if more than one unique instance of the
|
||||
* annotation is found
|
||||
*/
|
||||
static <A extends Annotation> A findUniqueAnnotation(Method method, Class<A> annotationType) {
|
||||
return findDistinctAnnotation(method, annotationType);
|
||||
static <A extends Annotation> A findUniqueAnnotation(Method method, Class<A> annotationType,
|
||||
Function<MergedAnnotation<A>, A> map) {
|
||||
return findDistinctAnnotation(method, annotationType, map);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,18 +126,18 @@ final class AuthorizationAnnotationUtils {
|
||||
* @throws AnnotationConfigurationException if more than one unique instance of the
|
||||
* annotation is found
|
||||
*/
|
||||
static <A extends Annotation> A findUniqueAnnotation(Class<?> type, Class<A> annotationType) {
|
||||
return findDistinctAnnotation(type, annotationType);
|
||||
static <A extends Annotation> A findUniqueAnnotation(Class<?> type, Class<A> annotationType,
|
||||
Function<MergedAnnotation<A>, A> map) {
|
||||
return findDistinctAnnotation(type, annotationType, map);
|
||||
}
|
||||
|
||||
private static <A extends Annotation> A findDistinctAnnotation(AnnotatedElement annotatedElement,
|
||||
Class<A> annotationType) {
|
||||
Class<A> annotationType, Function<MergedAnnotation<A>, A> map) {
|
||||
MergedAnnotations mergedAnnotations = MergedAnnotations.from(annotatedElement, SearchStrategy.TYPE_HIERARCHY,
|
||||
RepeatableContainers.none());
|
||||
|
||||
List<A> annotations = mergedAnnotations.stream(annotationType)
|
||||
.map(MergedAnnotation::withNonMergedAttributes)
|
||||
.map(MergedAnnotation::synthesize)
|
||||
.map(map)
|
||||
.distinct()
|
||||
.toList();
|
||||
|
||||
|
||||
@@ -46,7 +46,19 @@ public final class PostAuthorizeAuthorizationManager implements AuthorizationMan
|
||||
* @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.registry = new PostAuthorizeExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,16 +16,15 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* For internal use only, as this contract is likely to change.
|
||||
@@ -36,21 +35,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
|
||||
|
||||
private final MethodSecurityExpressionHandler expressionHandler;
|
||||
|
||||
PostAuthorizeExpressionAttributeRegistry() {
|
||||
this(new DefaultMethodSecurityExpressionHandler());
|
||||
}
|
||||
|
||||
PostAuthorizeExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
|
||||
@@ -59,15 +43,14 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
|
||||
if (postAuthorize == null) {
|
||||
return ExpressionAttribute.NULL_ATTRIBUTE;
|
||||
}
|
||||
Expression postAuthorizeExpression = this.expressionHandler.getExpressionParser()
|
||||
.parseExpression(postAuthorize.value());
|
||||
return new ExpressionAttribute(postAuthorizeExpression);
|
||||
Expression expression = getExpressionHandler().getExpressionParser().parseExpression(postAuthorize.value());
|
||||
return new ExpressionAttribute(expression);
|
||||
}
|
||||
|
||||
private PostAuthorize findPostAuthorizeAnnotation(Method method, Class<?> targetClass) {
|
||||
PostAuthorize postAuthorize = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PostAuthorize.class);
|
||||
return (postAuthorize != null) ? postAuthorize : AuthorizationAnnotationUtils
|
||||
.findUniqueAnnotation(targetClass(method, targetClass), PostAuthorize.class);
|
||||
Function<AnnotatedElement, PostAuthorize> lookup = findUniqueAnnotation(PostAuthorize.class);
|
||||
PostAuthorize postAuthorize = lookup.apply(method);
|
||||
return (postAuthorize != null) ? postAuthorize : lookup.apply(targetClass(method, targetClass));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.util.Assert;
|
||||
public final class PostAuthorizeReactiveAuthorizationManager
|
||||
implements ReactiveAuthorizationManager<MethodInvocationResult> {
|
||||
|
||||
private final PostAuthorizeExpressionAttributeRegistry registry;
|
||||
private final PostAuthorizeExpressionAttributeRegistry registry = new PostAuthorizeExpressionAttributeRegistry();
|
||||
|
||||
public PostAuthorizeReactiveAuthorizationManager() {
|
||||
this(new DefaultMethodSecurityExpressionHandler());
|
||||
@@ -46,7 +46,19 @@ public final class PostAuthorizeReactiveAuthorizationManager
|
||||
|
||||
public PostAuthorizeReactiveAuthorizationManager(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.registry = new PostAuthorizeExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,7 +67,19 @@ public final class PostFilterAuthorizationMethodInterceptor
|
||||
* @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.registry = new PostFilterExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,7 +49,7 @@ import org.springframework.util.Assert;
|
||||
public final class PostFilterAuthorizationReactiveMethodInterceptor
|
||||
implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
|
||||
|
||||
private final PostFilterExpressionAttributeRegistry registry;
|
||||
private final PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry();
|
||||
|
||||
private final Pointcut pointcut = AuthorizationMethodPointcuts.forAnnotations(PostFilter.class);
|
||||
|
||||
@@ -67,7 +67,19 @@ public final class PostFilterAuthorizationReactiveMethodInterceptor
|
||||
*/
|
||||
public PostFilterAuthorizationReactiveMethodInterceptor(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.registry = new PostFilterExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.prepost.PostFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* For internal use only, as this contract is likely to change.
|
||||
@@ -35,21 +34,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
|
||||
|
||||
private final MethodSecurityExpressionHandler expressionHandler;
|
||||
|
||||
PostFilterExpressionAttributeRegistry() {
|
||||
this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
}
|
||||
|
||||
PostFilterExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
|
||||
@@ -58,15 +42,15 @@ final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttr
|
||||
if (postFilter == null) {
|
||||
return ExpressionAttribute.NULL_ATTRIBUTE;
|
||||
}
|
||||
Expression postFilterExpression = this.expressionHandler.getExpressionParser()
|
||||
Expression postFilterExpression = getExpressionHandler().getExpressionParser()
|
||||
.parseExpression(postFilter.value());
|
||||
return new ExpressionAttribute(postFilterExpression);
|
||||
}
|
||||
|
||||
private PostFilter findPostFilterAnnotation(Method method, Class<?> targetClass) {
|
||||
PostFilter postFilter = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PostFilter.class);
|
||||
return (postFilter != null) ? postFilter
|
||||
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass(method, targetClass), PostFilter.class);
|
||||
Function<AnnotatedElement, PostFilter> lookup = findUniqueAnnotation(PostFilter.class);
|
||||
PostFilter postFilter = lookup.apply(method);
|
||||
return (postFilter != null) ? postFilter : lookup.apply(targetClass(method, targetClass));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,19 @@ public final class PreAuthorizeAuthorizationManager implements AuthorizationMana
|
||||
* @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.registry = new PreAuthorizeExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,16 +16,15 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* For internal use only, as this contract is likely to change.
|
||||
@@ -36,25 +35,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
|
||||
|
||||
private final MethodSecurityExpressionHandler expressionHandler;
|
||||
|
||||
PreAuthorizeExpressionAttributeRegistry() {
|
||||
this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
}
|
||||
|
||||
PreAuthorizeExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MethodSecurityExpressionHandler}.
|
||||
* @return the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
ExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
|
||||
@@ -63,15 +43,14 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
|
||||
if (preAuthorize == null) {
|
||||
return ExpressionAttribute.NULL_ATTRIBUTE;
|
||||
}
|
||||
Expression preAuthorizeExpression = this.expressionHandler.getExpressionParser()
|
||||
.parseExpression(preAuthorize.value());
|
||||
return new ExpressionAttribute(preAuthorizeExpression);
|
||||
Expression expression = getExpressionHandler().getExpressionParser().parseExpression(preAuthorize.value());
|
||||
return new ExpressionAttribute(expression);
|
||||
}
|
||||
|
||||
private PreAuthorize findPreAuthorizeAnnotation(Method method, Class<?> targetClass) {
|
||||
PreAuthorize preAuthorize = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PreAuthorize.class);
|
||||
return (preAuthorize != null) ? preAuthorize : AuthorizationAnnotationUtils
|
||||
.findUniqueAnnotation(targetClass(method, targetClass), PreAuthorize.class);
|
||||
Function<AnnotatedElement, PreAuthorize> lookup = findUniqueAnnotation(PreAuthorize.class);
|
||||
PreAuthorize preAuthorize = lookup.apply(method);
|
||||
return (preAuthorize != null) ? preAuthorize : lookup.apply(targetClass(method, targetClass));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public final class PreAuthorizeReactiveAuthorizationManager implements ReactiveAuthorizationManager<MethodInvocation> {
|
||||
|
||||
private final PreAuthorizeExpressionAttributeRegistry registry;
|
||||
private final PreAuthorizeExpressionAttributeRegistry registry = new PreAuthorizeExpressionAttributeRegistry();
|
||||
|
||||
public PreAuthorizeReactiveAuthorizationManager() {
|
||||
this(new DefaultMethodSecurityExpressionHandler());
|
||||
@@ -45,7 +45,19 @@ public final class PreAuthorizeReactiveAuthorizationManager implements ReactiveA
|
||||
|
||||
public PreAuthorizeReactiveAuthorizationManager(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.registry = new PreAuthorizeExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,19 @@ public final class PreFilterAuthorizationMethodInterceptor
|
||||
* @param expressionHandler the {@link MethodSecurityExpressionHandler} to use
|
||||
*/
|
||||
public void setExpressionHandler(MethodSecurityExpressionHandler expressionHandler) {
|
||||
this.registry = new PreFilterExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ import org.springframework.util.StringUtils;
|
||||
public final class PreFilterAuthorizationReactiveMethodInterceptor
|
||||
implements Ordered, MethodInterceptor, PointcutAdvisor, AopInfrastructureBean {
|
||||
|
||||
private final PreFilterExpressionAttributeRegistry registry;
|
||||
private final PreFilterExpressionAttributeRegistry registry = new PreFilterExpressionAttributeRegistry();
|
||||
|
||||
private final Pointcut pointcut = AuthorizationMethodPointcuts.forAnnotations(PreFilter.class);
|
||||
|
||||
@@ -70,7 +70,19 @@ public final class PreFilterAuthorizationReactiveMethodInterceptor
|
||||
*/
|
||||
public PreFilterAuthorizationReactiveMethodInterceptor(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.registry = new PreFilterExpressionAttributeRegistry(expressionHandler);
|
||||
this.registry.setExpressionHandler(expressionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure pre/post-authorization template resolution
|
||||
* <p>
|
||||
* By default, this value is <code>null</code>, which indicates that templates should
|
||||
* not be resolved.
|
||||
* @param defaults - whether to resolve pre/post-authorization templates parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
|
||||
this.registry.setTemplateDefaults(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.prepost.PreFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* For internal use only, as this contract is likely to change.
|
||||
@@ -36,21 +35,6 @@ import org.springframework.util.Assert;
|
||||
final class PreFilterExpressionAttributeRegistry
|
||||
extends AbstractExpressionAttributeRegistry<PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute> {
|
||||
|
||||
private final MethodSecurityExpressionHandler expressionHandler;
|
||||
|
||||
PreFilterExpressionAttributeRegistry() {
|
||||
this.expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
}
|
||||
|
||||
PreFilterExpressionAttributeRegistry(MethodSecurityExpressionHandler expressionHandler) {
|
||||
Assert.notNull(expressionHandler, "expressionHandler cannot be null");
|
||||
this.expressionHandler = expressionHandler;
|
||||
}
|
||||
|
||||
MethodSecurityExpressionHandler getExpressionHandler() {
|
||||
return this.expressionHandler;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
PreFilterExpressionAttribute resolveAttribute(Method method, Class<?> targetClass) {
|
||||
@@ -59,15 +43,15 @@ final class PreFilterExpressionAttributeRegistry
|
||||
if (preFilter == null) {
|
||||
return PreFilterExpressionAttribute.NULL_ATTRIBUTE;
|
||||
}
|
||||
Expression preFilterExpression = this.expressionHandler.getExpressionParser()
|
||||
Expression preFilterExpression = getExpressionHandler().getExpressionParser()
|
||||
.parseExpression(preFilter.value());
|
||||
return new PreFilterExpressionAttribute(preFilterExpression, preFilter.filterTarget());
|
||||
}
|
||||
|
||||
private PreFilter findPreFilterAnnotation(Method method, Class<?> targetClass) {
|
||||
PreFilter preFilter = AuthorizationAnnotationUtils.findUniqueAnnotation(method, PreFilter.class);
|
||||
return (preFilter != null) ? preFilter
|
||||
: AuthorizationAnnotationUtils.findUniqueAnnotation(targetClass(method, targetClass), PreFilter.class);
|
||||
Function<AnnotatedElement, PreFilter> lookup = findUniqueAnnotation(PreFilter.class);
|
||||
PreFilter preFilter = lookup.apply(method);
|
||||
return (preFilter != null) ? preFilter : lookup.apply(targetClass(method, targetClass));
|
||||
}
|
||||
|
||||
static final class PreFilterExpressionAttribute extends ExpressionAttribute {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization.method;
|
||||
|
||||
/**
|
||||
* A component for configuring various cross-cutting aspects of pre/post method security
|
||||
*
|
||||
* @author Josh Cummings
|
||||
* @since 6.3
|
||||
* @see org.springframework.security.access.prepost.PreAuthorize
|
||||
* @see org.springframework.security.access.prepost.PostAuthorize
|
||||
* @see org.springframework.security.access.prepost.PreFilter
|
||||
* @see org.springframework.security.access.prepost.PostFilter
|
||||
*/
|
||||
public final class PrePostTemplateDefaults {
|
||||
|
||||
private boolean ignoreUnknown = true;
|
||||
|
||||
/**
|
||||
* Whether template resolution should ignore placeholders it doesn't recognize.
|
||||
* <p>
|
||||
* By default, this value is <code>true</code>.
|
||||
* @since 6.3
|
||||
*/
|
||||
public boolean isIgnoreUnknown() {
|
||||
return this.ignoreUnknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure template resolution to ignore unknown placeholders. When set to
|
||||
* <code>false</code>, template resolution will throw an exception for unknown
|
||||
* placeholders.
|
||||
* <p>
|
||||
* By default, this value is <code>true</code>.
|
||||
* @param ignoreUnknown - whether to ignore unknown placeholders parameters
|
||||
* @since 6.3
|
||||
*/
|
||||
public void setIgnoreUnknown(boolean ignoreUnknown) {
|
||||
this.ignoreUnknown = ignoreUnknown;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user