Add meta-annotation parameter support

Closes gh-14480
This commit is contained in:
Josh Cummings
2024-01-22 16:29:47 -07:00
parent 347eeb17d5
commit 4d383023cb
19 changed files with 633 additions and 127 deletions

View File

@@ -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.

View File

@@ -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();

View File

@@ -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);
}
/**

View File

@@ -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));
}
}

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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));
}
}

View File

@@ -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);
}
/**

View File

@@ -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));
}
}

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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 {

View File

@@ -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;
}
}