Polish Annotation API

Rename to a class that isn't focused on the synthesis implementation detail.
Also add Security to the front of the name to clarify that it is only intended
for security annotations, reminiscent of SecurityMetadataSource.

Refine method signatures to better articulate supported use cases.

Issue gh-15286
This commit is contained in:
Josh Cummings 2024-08-29 17:24:57 -06:00
parent cc6de8fa5d
commit 626610a975
No known key found for this signature in database
GPG Key ID: A306A51F43B8E5A5
20 changed files with 298 additions and 233 deletions

View File

@ -34,8 +34,8 @@ import org.springframework.security.authorization.AuthoritiesAuthorizationManage
import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer; import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.AnnotationSynthesizers; import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -95,7 +95,7 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
private final class Jsr250AuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry { private final class Jsr250AuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry {
private final AnnotationSynthesizer<?> synthesizer = AnnotationSynthesizers private final SecurityAnnotationScanner<?> scanner = SecurityAnnotationScanners
.requireUnique(List.of(DenyAll.class, PermitAll.class, RolesAllowed.class)); .requireUnique(List.of(DenyAll.class, PermitAll.class, RolesAllowed.class));
@NonNull @NonNull
@ -117,7 +117,7 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
private Annotation findJsr250Annotation(Method method, Class<?> targetClass) { private Annotation findJsr250Annotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = (targetClass != null) ? targetClass : method.getDeclaringClass(); Class<?> targetClassToUse = (targetClass != null) ? targetClass : method.getDeclaringClass();
return this.synthesizer.synthesize(method, targetClassToUse); return this.scanner.scan(method, targetClassToUse);
} }
private Set<String> getAllowedRolesWithPrefix(RolesAllowed rolesAllowed) { private Set<String> getAllowedRolesWithPrefix(RolesAllowed rolesAllowed) {

View File

@ -25,9 +25,9 @@ import reactor.util.annotation.NonNull;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -41,12 +41,12 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
private final MethodAuthorizationDeniedHandler defaultHandler = new ThrowingMethodAuthorizationDeniedHandler(); private final MethodAuthorizationDeniedHandler defaultHandler = new ThrowingMethodAuthorizationDeniedHandler();
private final AnnotationSynthesizer<HandleAuthorizationDenied> handleAuthorizationDeniedSynthesizer = AnnotationSynthesizers private final SecurityAnnotationScanner<HandleAuthorizationDenied> handleAuthorizationDeniedScanner = SecurityAnnotationScanners
.requireUnique(HandleAuthorizationDenied.class); .requireUnique(HandleAuthorizationDenied.class);
private Function<Class<? extends MethodAuthorizationDeniedHandler>, MethodAuthorizationDeniedHandler> handlerResolver; private Function<Class<? extends MethodAuthorizationDeniedHandler>, MethodAuthorizationDeniedHandler> handlerResolver;
private AnnotationSynthesizer<PostAuthorize> postAuthorizeSynthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<PostAuthorize> postAuthorizeScanner = SecurityAnnotationScanners
.requireUnique(PostAuthorize.class); .requireUnique(PostAuthorize.class);
PostAuthorizeExpressionAttributeRegistry() { PostAuthorizeExpressionAttributeRegistry() {
@ -68,8 +68,7 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
private MethodAuthorizationDeniedHandler resolveHandler(Method method, Class<?> targetClass) { private MethodAuthorizationDeniedHandler resolveHandler(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
HandleAuthorizationDenied deniedHandler = this.handleAuthorizationDeniedSynthesizer.synthesize(method, HandleAuthorizationDenied deniedHandler = this.handleAuthorizationDeniedScanner.scan(method, targetClassToUse);
targetClassToUse);
if (deniedHandler != null) { if (deniedHandler != null) {
return this.handlerResolver.apply(deniedHandler.handlerClass()); return this.handlerResolver.apply(deniedHandler.handlerClass());
} }
@ -78,7 +77,7 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
private PostAuthorize findPostAuthorizeAnnotation(Method method, Class<?> targetClass) { private PostAuthorize findPostAuthorizeAnnotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
return this.postAuthorizeSynthesizer.synthesize(method, targetClassToUse); return this.postAuthorizeScanner.scan(method, targetClassToUse);
} }
/** /**
@ -92,7 +91,7 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
} }
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.postAuthorizeSynthesizer = AnnotationSynthesizers.requireUnique(PostAuthorize.class, templateDefaults); this.postAuthorizeScanner = SecurityAnnotationScanners.requireUnique(PostAuthorize.class, templateDefaults);
} }
private MethodAuthorizationDeniedHandler resolveHandler(ApplicationContext context, private MethodAuthorizationDeniedHandler resolveHandler(ApplicationContext context,

View File

@ -21,9 +21,9 @@ import java.lang.reflect.Method;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.security.access.prepost.PostFilter; import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
/** /**
* For internal use only, as this contract is likely to change. * For internal use only, as this contract is likely to change.
@ -34,7 +34,7 @@ import org.springframework.security.core.annotation.AnnotationTemplateExpression
*/ */
final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> { final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttributeRegistry<ExpressionAttribute> {
private AnnotationSynthesizer<PostFilter> synthesizer = AnnotationSynthesizers.requireUnique(PostFilter.class); private SecurityAnnotationScanner<PostFilter> scanner = SecurityAnnotationScanners.requireUnique(PostFilter.class);
@NonNull @NonNull
@Override @Override
@ -49,12 +49,12 @@ final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttr
} }
void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) { void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(PostFilter.class, defaults); this.scanner = SecurityAnnotationScanners.requireUnique(PostFilter.class, defaults);
} }
private PostFilter findPostFilterAnnotation(Method method, Class<?> targetClass) { private PostFilter findPostFilterAnnotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
return this.synthesizer.synthesize(method, targetClassToUse); return this.scanner.scan(method, targetClassToUse);
} }
} }

View File

@ -25,9 +25,9 @@ import reactor.util.annotation.NonNull;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -41,12 +41,12 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
private final MethodAuthorizationDeniedHandler defaultHandler = new ThrowingMethodAuthorizationDeniedHandler(); private final MethodAuthorizationDeniedHandler defaultHandler = new ThrowingMethodAuthorizationDeniedHandler();
private final AnnotationSynthesizer<HandleAuthorizationDenied> handleAuthorizationDeniedSynthesizer = AnnotationSynthesizers private final SecurityAnnotationScanner<HandleAuthorizationDenied> handleAuthorizationDeniedScanner = SecurityAnnotationScanners
.requireUnique(HandleAuthorizationDenied.class); .requireUnique(HandleAuthorizationDenied.class);
private Function<Class<? extends MethodAuthorizationDeniedHandler>, MethodAuthorizationDeniedHandler> handlerResolver; private Function<Class<? extends MethodAuthorizationDeniedHandler>, MethodAuthorizationDeniedHandler> handlerResolver;
private AnnotationSynthesizer<PreAuthorize> preAuthorizeSynthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<PreAuthorize> preAuthorizeScanner = SecurityAnnotationScanners
.requireUnique(PreAuthorize.class); .requireUnique(PreAuthorize.class);
PreAuthorizeExpressionAttributeRegistry() { PreAuthorizeExpressionAttributeRegistry() {
@ -68,8 +68,7 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
private MethodAuthorizationDeniedHandler resolveHandler(Method method, Class<?> targetClass) { private MethodAuthorizationDeniedHandler resolveHandler(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
HandleAuthorizationDenied deniedHandler = this.handleAuthorizationDeniedSynthesizer.synthesize(method, HandleAuthorizationDenied deniedHandler = this.handleAuthorizationDeniedScanner.scan(method, targetClassToUse);
targetClassToUse);
if (deniedHandler != null) { if (deniedHandler != null) {
return this.handlerResolver.apply(deniedHandler.handlerClass()); return this.handlerResolver.apply(deniedHandler.handlerClass());
} }
@ -78,7 +77,7 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
private PreAuthorize findPreAuthorizeAnnotation(Method method, Class<?> targetClass) { private PreAuthorize findPreAuthorizeAnnotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
return this.preAuthorizeSynthesizer.synthesize(method, targetClassToUse); return this.preAuthorizeScanner.scan(method, targetClassToUse);
} }
/** /**
@ -92,7 +91,7 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
} }
void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) { void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
this.preAuthorizeSynthesizer = AnnotationSynthesizers.requireUnique(PreAuthorize.class, defaults); this.preAuthorizeScanner = SecurityAnnotationScanners.requireUnique(PreAuthorize.class, defaults);
} }
private MethodAuthorizationDeniedHandler resolveHandler(ApplicationContext context, private MethodAuthorizationDeniedHandler resolveHandler(ApplicationContext context,

View File

@ -21,9 +21,9 @@ import java.lang.reflect.Method;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.security.access.prepost.PreFilter; import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
/** /**
* For internal use only, as this contract is likely to change. * For internal use only, as this contract is likely to change.
@ -35,7 +35,7 @@ import org.springframework.security.core.annotation.AnnotationTemplateExpression
final class PreFilterExpressionAttributeRegistry final class PreFilterExpressionAttributeRegistry
extends AbstractExpressionAttributeRegistry<PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute> { extends AbstractExpressionAttributeRegistry<PreFilterExpressionAttributeRegistry.PreFilterExpressionAttribute> {
private AnnotationSynthesizer<PreFilter> synthesizer = AnnotationSynthesizers.requireUnique(PreFilter.class); private SecurityAnnotationScanner<PreFilter> scanner = SecurityAnnotationScanners.requireUnique(PreFilter.class);
@NonNull @NonNull
@Override @Override
@ -50,12 +50,12 @@ final class PreFilterExpressionAttributeRegistry
} }
void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) { void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(PreFilter.class, defaults); this.scanner = SecurityAnnotationScanners.requireUnique(PreFilter.class, defaults);
} }
private PreFilter findPreFilterAnnotation(Method method, Class<?> targetClass) { private PreFilter findPreFilterAnnotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = targetClass(method, targetClass); Class<?> targetClassToUse = targetClass(method, targetClass);
return this.synthesizer.synthesize(method, targetClassToUse); return this.scanner.scan(method, targetClassToUse);
} }
static final class PreFilterExpressionAttribute extends ExpressionAttribute { static final class PreFilterExpressionAttribute extends ExpressionAttribute {

View File

@ -32,8 +32,8 @@ import org.springframework.security.authorization.AuthoritiesAuthorizationManage
import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager; import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer; import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.AnnotationSynthesizers; import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -51,7 +51,7 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
private final Map<MethodClassKey, Set<String>> cachedAuthorities = new ConcurrentHashMap<>(); private final Map<MethodClassKey, Set<String>> cachedAuthorities = new ConcurrentHashMap<>();
private final AnnotationSynthesizer<Secured> synthesizer = AnnotationSynthesizers.requireUnique(Secured.class); private final SecurityAnnotationScanner<Secured> scanner = SecurityAnnotationScanners.requireUnique(Secured.class);
/** /**
* Sets an {@link AuthorizationManager} that accepts a collection of authority * Sets an {@link AuthorizationManager} that accepts a collection of authority
@ -95,7 +95,7 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
private Secured findSecuredAnnotation(Method method, Class<?> targetClass) { private Secured findSecuredAnnotation(Method method, Class<?> targetClass) {
Class<?> targetClassToUse = (targetClass != null) ? targetClass : method.getDeclaringClass(); Class<?> targetClassToUse = (targetClass != null) ? targetClass : method.getDeclaringClass();
return this.synthesizer.synthesize(method, targetClassToUse); return this.scanner.scan(method, targetClassToUse);
} }
} }

View File

@ -0,0 +1,66 @@
/*
* 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.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* An abstract class to hide the {@link MergedAnnotation} implementation details.
*
* <p>
* Also handy for allowing each scanner to delegate to another without needing to
* synthesize twice.
*/
abstract class AbstractSecurityAnnotationScanner<A extends Annotation> implements SecurityAnnotationScanner<A> {
/**
* {@inheritDoc}
**/
@Nullable
@Override
public A scan(Method method, Class<?> targetClass) {
Assert.notNull(targetClass, "targetClass cannot be null");
MergedAnnotation<A> annotation = merge(method, targetClass);
if (annotation == null) {
return null;
}
return annotation.synthesize();
}
/**
* {@inheritDoc}
**/
@Nullable
@Override
public A scan(Parameter parameter) {
MergedAnnotation<A> annotation = merge(parameter, null);
if (annotation == null) {
return null;
}
return annotation.synthesize();
}
abstract MergedAnnotation<A> merge(AnnotatedElement element, Class<?> targetClass);
}

View File

@ -1,81 +0,0 @@
/*
* 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.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.List;
/**
* Factory for creating {@link AnnotationSynthesizer} instances.
*
* @author Josh Cummings
* @since 6.4
*/
public final class AnnotationSynthesizers {
private AnnotationSynthesizers() {
}
/**
* Create a {@link AnnotationSynthesizer} that requires synthesized annotations to be
* unique on the given {@link AnnotatedElement}.
* @param type the annotation type
* @param <A> the annotation type
* @return the default {@link AnnotationSynthesizer}
*/
public static <A extends Annotation> AnnotationSynthesizer<A> requireUnique(Class<A> type) {
return new UniqueMergedAnnotationSynthesizer<>(type);
}
/**
* Create a {@link AnnotationSynthesizer} that requires synthesized annotations to be
* unique on the given {@link AnnotatedElement}.
*
* <p>
* When a {@link AnnotationTemplateExpressionDefaults} is provided, it will return a
* synthesizer that supports placeholders in the annotation's attributes in addition
* to the meta-annotation synthesizing provided by {@link #requireUnique(Class)}.
* @param type the annotation type
* @param templateDefaults the defaults for resolving placeholders in the annotation's
* attributes
* @param <A> the annotation type
* @return the default {@link AnnotationSynthesizer}
*/
public static <A extends Annotation> AnnotationSynthesizer<A> requireUnique(Class<A> type,
AnnotationTemplateExpressionDefaults templateDefaults) {
if (templateDefaults == null) {
return new UniqueMergedAnnotationSynthesizer<>(type);
}
return new ExpressionTemplateAnnotationSynthesizer<>(type, templateDefaults);
}
/**
* Create a {@link AnnotationSynthesizer} that requires synthesized annotations to be
* unique on the given {@link AnnotatedElement}. Supplying multiple types implies that
* the synthesized annotation must be unique across all specified types.
* @param types the annotation types
* @return the default {@link AnnotationSynthesizer}
*/
public static AnnotationSynthesizer<Annotation> requireUnique(List<Class<? extends Annotation>> types) {
List<Class<Annotation>> casted = new ArrayList<>();
types.forEach((type) -> casted.add((Class<Annotation>) type));
return new UniqueMergedAnnotationSynthesizer<>(casted);
}
}

View File

@ -35,8 +35,8 @@ import org.springframework.util.PropertyPlaceholderHelper;
* *
* <p> * <p>
* Note that in all cases, Spring Security does not allow for repeatable annotations. So * Note that in all cases, Spring Security does not allow for repeatable annotations. So
* this class delegates to {@link UniqueMergedAnnotationSynthesizer} in order to error if * this class delegates to {@link UniqueSecurityAnnotationScanner} in order to error if a
* a repeat is discovered. * repeat is discovered.
* *
* <p> * <p>
* It supports meta-annotations with placeholders, like the following: * It supports meta-annotations with placeholders, like the following:
@ -49,8 +49,8 @@ import org.springframework.util.PropertyPlaceholderHelper;
* </pre> * </pre>
* *
* <p> * <p>
* In that case, you could use an {@link ExpressionTemplateAnnotationSynthesizer} of type * In that case, you could use an {@link ExpressionTemplateSecurityAnnotationScanner} of
* {@link org.springframework.security.access.prepost.PreAuthorize} to synthesize any * type {@link org.springframework.security.access.prepost.PreAuthorize} to synthesize any
* {@code @HasRole} annotation found on a given {@link AnnotatedElement}. * {@code @HasRole} annotation found on a given {@link AnnotatedElement}.
* *
* <p> * <p>
@ -61,11 +61,12 @@ import org.springframework.util.PropertyPlaceholderHelper;
* @author Josh Cummings * @author Josh Cummings
* @since 6.4 * @since 6.4
*/ */
final class ExpressionTemplateAnnotationSynthesizer<A extends Annotation> extends AbstractAnnotationSynthesizer<A> { final class ExpressionTemplateSecurityAnnotationScanner<A extends Annotation>
extends AbstractSecurityAnnotationScanner<A> {
private final Class<A> type; private final Class<A> type;
private final UniqueMergedAnnotationSynthesizer<A> unique; private final UniqueSecurityAnnotationScanner<A> unique;
private final AnnotationTemplateExpressionDefaults templateDefaults; private final AnnotationTemplateExpressionDefaults templateDefaults;
@ -73,11 +74,11 @@ final class ExpressionTemplateAnnotationSynthesizer<A extends Annotation> extend
private final Map<MethodClassKey, MergedAnnotation<A>> uniqueMethodAnnotationCache = new HashMap<>(); private final Map<MethodClassKey, MergedAnnotation<A>> uniqueMethodAnnotationCache = new HashMap<>();
ExpressionTemplateAnnotationSynthesizer(Class<A> type, AnnotationTemplateExpressionDefaults templateDefaults) { ExpressionTemplateSecurityAnnotationScanner(Class<A> type, AnnotationTemplateExpressionDefaults templateDefaults) {
Assert.notNull(type, "type cannot be null"); Assert.notNull(type, "type cannot be null");
Assert.notNull(templateDefaults, "templateDefaults cannot be null"); Assert.notNull(templateDefaults, "templateDefaults cannot be null");
this.type = type; this.type = type;
this.unique = new UniqueMergedAnnotationSynthesizer<>(type); this.unique = new UniqueSecurityAnnotationScanner<>(type);
this.templateDefaults = templateDefaults; this.templateDefaults = templateDefaults;
} }

View File

@ -23,7 +23,7 @@ import java.lang.reflect.Parameter;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
/** /**
* An interface to search for and synthesize an annotation on a type, method, or method * An interface to scan for and synthesize an annotation on a type, method, or method
* parameter into an annotation of type {@code <A>}. * parameter into an annotation of type {@code <A>}.
* *
* <p> * <p>
@ -43,13 +43,13 @@ import org.springframework.lang.Nullable;
* @param <A> the annotation to search for and synthesize * @param <A> the annotation to search for and synthesize
* @author Josh Cummings * @author Josh Cummings
* @since 6.4 * @since 6.4
* @see UniqueMergedAnnotationSynthesizer * @see UniqueSecurityAnnotationScanner
* @see ExpressionTemplateAnnotationSynthesizer * @see ExpressionTemplateSecurityAnnotationScanner
*/ */
public interface AnnotationSynthesizer<A extends Annotation> { public interface SecurityAnnotationScanner<A extends Annotation> {
/** /**
* Synthesize an annotation of type {@code A} from the given method. * Scan for an annotation of type {@code A}, starting from the given method.
* *
* <p> * <p>
* Implementations should fail if they encounter more than one annotation of that type * Implementations should fail if they encounter more than one annotation of that type
@ -63,10 +63,10 @@ public interface AnnotationSynthesizer<A extends Annotation> {
* @return the synthesized annotation or {@code null} if not found * @return the synthesized annotation or {@code null} if not found
*/ */
@Nullable @Nullable
A synthesize(Method method, Class<?> targetClass); A scan(Method method, Class<?> targetClass);
/** /**
* Synthesize an annotation of type {@code A} from the given method parameter. * Scan for an annotation of type {@code A}, starting from the given method parameter.
* *
* <p> * <p>
* Implementations should fail if they encounter more than one annotation of that type * Implementations should fail if they encounter more than one annotation of that type
@ -79,6 +79,6 @@ public interface AnnotationSynthesizer<A extends Annotation> {
* @return the synthesized annotation or {@code null} if not found * @return the synthesized annotation or {@code null} if not found
*/ */
@Nullable @Nullable
A synthesize(Parameter parameter); A scan(Parameter parameter);
} }

View File

@ -0,0 +1,81 @@
/*
* 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.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.List;
/**
* Factory for creating {@link SecurityAnnotationScanner} instances.
*
* @author Josh Cummings
* @since 6.4
*/
public final class SecurityAnnotationScanners {
private SecurityAnnotationScanners() {
}
/**
* Create a {@link SecurityAnnotationScanner} that requires synthesized annotations to
* be unique on the given {@link AnnotatedElement}.
* @param type the annotation type
* @param <A> the annotation type
* @return the default {@link SecurityAnnotationScanner}
*/
public static <A extends Annotation> SecurityAnnotationScanner<A> requireUnique(Class<A> type) {
return new UniqueSecurityAnnotationScanner<>(type);
}
/**
* Create a {@link SecurityAnnotationScanner} that requires synthesized annotations to
* be unique on the given {@link AnnotatedElement}.
*
* <p>
* When a {@link AnnotationTemplateExpressionDefaults} is provided, it will return a
* scanner that supports placeholders in the annotation's attributes in addition to
* the meta-annotation synthesizing provided by {@link #requireUnique(Class)}.
* @param type the annotation type
* @param templateDefaults the defaults for resolving placeholders in the annotation's
* attributes
* @param <A> the annotation type
* @return the default {@link SecurityAnnotationScanner}
*/
public static <A extends Annotation> SecurityAnnotationScanner<A> requireUnique(Class<A> type,
AnnotationTemplateExpressionDefaults templateDefaults) {
if (templateDefaults == null) {
return new UniqueSecurityAnnotationScanner<>(type);
}
return new ExpressionTemplateSecurityAnnotationScanner<>(type, templateDefaults);
}
/**
* Create a {@link SecurityAnnotationScanner} that requires synthesized annotations to
* be unique on the given {@link AnnotatedElement}. Supplying multiple types implies
* that the synthesized annotation must be unique across all specified types.
* @param types the annotation types
* @return the default {@link SecurityAnnotationScanner}
*/
public static SecurityAnnotationScanner<Annotation> requireUnique(List<Class<? extends Annotation>> types) {
List<Class<Annotation>> casted = new ArrayList<>();
types.forEach((type) -> casted.add((Class<Annotation>) type));
return new UniqueSecurityAnnotationScanner<>(casted);
}
}

View File

@ -69,7 +69,7 @@ import org.springframework.util.ClassUtils;
* </pre> * </pre>
* *
* <p> * <p>
* In that case, you can use an {@link UniqueMergedAnnotationSynthesizer} of type * In that case, you can use an {@link UniqueSecurityAnnotationScanner} of type
* {@link org.springframework.security.access.prepost.PreAuthorize} to synthesize any * {@link org.springframework.security.access.prepost.PreAuthorize} to synthesize any
* {@code @HasRole} annotation found on a given method or class into its * {@code @HasRole} annotation found on a given method or class into its
* {@link org.springframework.security.access.prepost.PreAuthorize} meta-annotation. * {@link org.springframework.security.access.prepost.PreAuthorize} meta-annotation.
@ -82,16 +82,16 @@ import org.springframework.util.ClassUtils;
* @author Josh Cummings * @author Josh Cummings
* @since 6.4 * @since 6.4
*/ */
final class UniqueMergedAnnotationSynthesizer<A extends Annotation> extends AbstractAnnotationSynthesizer<A> { final class UniqueSecurityAnnotationScanner<A extends Annotation> extends AbstractSecurityAnnotationScanner<A> {
private final List<Class<A>> types; private final List<Class<A>> types;
UniqueMergedAnnotationSynthesizer(Class<A> type) { UniqueSecurityAnnotationScanner(Class<A> type) {
Assert.notNull(type, "type cannot be null"); Assert.notNull(type, "type cannot be null");
this.types = List.of(type); this.types = List.of(type);
} }
UniqueMergedAnnotationSynthesizer(List<Class<A>> types) { UniqueSecurityAnnotationScanner(List<Class<A>> types) {
Assert.notNull(types, "types cannot be null"); Assert.notNull(types, "types cannot be null");
this.types = types; this.types = types;
} }

View File

@ -27,227 +27,227 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/** /**
* Tests for {@link UniqueMergedAnnotationSynthesizer} * Tests for {@link UniqueSecurityAnnotationScanner}
*/ */
public class UniqueMergedAnnotationSynthesizerTests { public class UniqueSecurityAnnotationScannerTests {
private UniqueMergedAnnotationSynthesizer<PreAuthorize> synthesizer = new UniqueMergedAnnotationSynthesizer<>( private UniqueSecurityAnnotationScanner<PreAuthorize> scanner = new UniqueSecurityAnnotationScanner<>(
PreAuthorize.class); PreAuthorize.class);
@Test @Test
void synthesizeWhenAnnotationOnInterfaceThenResolves() throws Exception { void scanWhenAnnotationOnInterfaceThenResolves() throws Exception {
Method method = AnnotationOnInterface.class.getDeclaredMethod("method"); Method method = AnnotationOnInterface.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("one"); assertThat(preAuthorize.value()).isEqualTo("one");
} }
@Test @Test
void synthesizeWhenAnnotationOnMethodThenResolves() throws Exception { void scanWhenAnnotationOnMethodThenResolves() throws Exception {
Method method = AnnotationOnInterfaceMethod.class.getDeclaredMethod("method"); Method method = AnnotationOnInterfaceMethod.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("three"); assertThat(preAuthorize.value()).isEqualTo("three");
} }
@Test @Test
void synthesizeWhenAnnotationOnClassThenResolves() throws Exception { void scanWhenAnnotationOnClassThenResolves() throws Exception {
Method method = AnnotationOnClass.class.getDeclaredMethod("method"); Method method = AnnotationOnClass.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("five"); assertThat(preAuthorize.value()).isEqualTo("five");
} }
@Test @Test
void synthesizeWhenAnnotationOnClassMethodThenResolves() throws Exception { void scanWhenAnnotationOnClassMethodThenResolves() throws Exception {
Method method = AnnotationOnClassMethod.class.getDeclaredMethod("method"); Method method = AnnotationOnClassMethod.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("six"); assertThat(preAuthorize.value()).isEqualTo("six");
} }
@Test @Test
void synthesizeWhenInterfaceOverridingAnnotationOnInterfaceThenResolves() throws Exception { void scanWhenInterfaceOverridingAnnotationOnInterfaceThenResolves() throws Exception {
Method method = InterfaceMethodOverridingAnnotationOnInterface.class.getDeclaredMethod("method"); Method method = InterfaceMethodOverridingAnnotationOnInterface.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("eight"); assertThat(preAuthorize.value()).isEqualTo("eight");
} }
@Test @Test
void synthesizeWhenInterfaceOverridingMultipleInterfaceInheritanceThenResolves() throws Exception { void scanWhenInterfaceOverridingMultipleInterfaceInheritanceThenResolves() throws Exception {
Method method = ClassInheritingInterfaceOverridingMultipleInterfaceInheritance.class Method method = ClassInheritingInterfaceOverridingMultipleInterfaceInheritance.class
.getDeclaredMethod("method"); .getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("ten"); assertThat(preAuthorize.value()).isEqualTo("ten");
} }
@Test @Test
void synthesizeWhenInterfaceMethodOverridingAnnotationOnInterfaceThenResolves() throws Exception { void scanWhenInterfaceMethodOverridingAnnotationOnInterfaceThenResolves() throws Exception {
Method method = InterfaceMethodOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method"); Method method = InterfaceMethodOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("eleven"); assertThat(preAuthorize.value()).isEqualTo("eleven");
} }
@Test @Test
void synthesizeWhenClassMultipleInheritanceThenException() throws Exception { void scanWhenClassMultipleInheritanceThenException() throws Exception {
Method method = ClassAttemptingMultipleInterfaceInheritance.class.getDeclaredMethod("method"); Method method = ClassAttemptingMultipleInterfaceInheritance.class.getDeclaredMethod("method");
assertThatExceptionOfType(AnnotationConfigurationException.class) assertThatExceptionOfType(AnnotationConfigurationException.class)
.isThrownBy(() -> this.synthesizer.synthesize(method, method.getDeclaringClass())); .isThrownBy(() -> this.scanner.scan(method, method.getDeclaringClass()));
} }
// gh-15097 // gh-15097
@Test @Test
void synthesizeWhenClassOverridingMultipleInterfaceInheritanceThenResolves() throws Exception { void scanWhenClassOverridingMultipleInterfaceInheritanceThenResolves() throws Exception {
Method method = ClassOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method"); Method method = ClassOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("thirteen"); assertThat(preAuthorize.value()).isEqualTo("thirteen");
} }
@Test @Test
void synthesizeWhenClassMethodOverridingMultipleInterfaceInheritanceThenResolves() throws Exception { void scanWhenClassMethodOverridingMultipleInterfaceInheritanceThenResolves() throws Exception {
Method method = ClassMethodOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method"); Method method = ClassMethodOverridingMultipleInterfaceInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("fourteen"); assertThat(preAuthorize.value()).isEqualTo("fourteen");
} }
@Test @Test
void synthesizeWhenClassInheritingInterfaceOverridingInterfaceAnnotationThenResolves() throws Exception { void scanWhenClassInheritingInterfaceOverridingInterfaceAnnotationThenResolves() throws Exception {
Method method = ClassInheritingInterfaceOverridingInterfaceAnnotation.class.getDeclaredMethod("method"); Method method = ClassInheritingInterfaceOverridingInterfaceAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("seven"); assertThat(preAuthorize.value()).isEqualTo("seven");
} }
@Test @Test
void synthesizeWhenClassOverridingGrandparentInterfaceAnnotationThenResolves() throws Exception { void scanWhenClassOverridingGrandparentInterfaceAnnotationThenResolves() throws Exception {
Method method = ClassOverridingGrandparentInterfaceAnnotation.class.getDeclaredMethod("method"); Method method = ClassOverridingGrandparentInterfaceAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("sixteen"); assertThat(preAuthorize.value()).isEqualTo("sixteen");
} }
@Test @Test
void synthesizeWhenMethodOverridingGrandparentInterfaceAnnotationThenResolves() throws Exception { void scanWhenMethodOverridingGrandparentInterfaceAnnotationThenResolves() throws Exception {
Method method = MethodOverridingGrandparentInterfaceAnnotation.class.getDeclaredMethod("method"); Method method = MethodOverridingGrandparentInterfaceAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("seventeen"); assertThat(preAuthorize.value()).isEqualTo("seventeen");
} }
@Test @Test
void synthesizeWhenClassInheritingMethodOverriddenAnnotationThenResolves() throws Exception { void scanWhenClassInheritingMethodOverriddenAnnotationThenResolves() throws Exception {
Method method = ClassInheritingMethodOverriddenAnnotation.class.getDeclaredMethod("method"); Method method = ClassInheritingMethodOverriddenAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("eight"); assertThat(preAuthorize.value()).isEqualTo("eight");
} }
@Test @Test
void synthesizeWhenClassOverridingMethodOverriddenAnnotationThenResolves() throws Exception { void scanWhenClassOverridingMethodOverriddenAnnotationThenResolves() throws Exception {
Method method = ClassOverridingMethodOverriddenAnnotation.class.getDeclaredMethod("method"); Method method = ClassOverridingMethodOverriddenAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("eight"); assertThat(preAuthorize.value()).isEqualTo("eight");
} }
@Test @Test
void synthesizeWhenMethodOverridingMethodOverriddenAnnotationThenResolves() throws Exception { void scanWhenMethodOverridingMethodOverriddenAnnotationThenResolves() throws Exception {
Method method = MethodOverridingMethodOverriddenAnnotation.class.getDeclaredMethod("method"); Method method = MethodOverridingMethodOverriddenAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twenty"); assertThat(preAuthorize.value()).isEqualTo("twenty");
} }
@Test @Test
void synthesizeWhenClassInheritingMultipleInheritanceThenException() throws Exception { void scanWhenClassInheritingMultipleInheritanceThenException() throws Exception {
Method method = ClassInheritingMultipleInheritance.class.getDeclaredMethod("method"); Method method = ClassInheritingMultipleInheritance.class.getDeclaredMethod("method");
assertThatExceptionOfType(AnnotationConfigurationException.class) assertThatExceptionOfType(AnnotationConfigurationException.class)
.isThrownBy(() -> this.synthesizer.synthesize(method, method.getDeclaringClass())); .isThrownBy(() -> this.scanner.scan(method, method.getDeclaringClass()));
} }
@Test @Test
void synthesizeWhenClassOverridingMultipleInheritanceThenResolves() throws Exception { void scanWhenClassOverridingMultipleInheritanceThenResolves() throws Exception {
Method method = ClassOverridingMultipleInheritance.class.getDeclaredMethod("method"); Method method = ClassOverridingMultipleInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twentytwo"); assertThat(preAuthorize.value()).isEqualTo("twentytwo");
} }
@Test @Test
void synthesizeWhenMethodOverridingMultipleInheritanceThenResolves() throws Exception { void scanWhenMethodOverridingMultipleInheritanceThenResolves() throws Exception {
Method method = MethodOverridingMultipleInheritance.class.getDeclaredMethod("method"); Method method = MethodOverridingMultipleInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twentythree"); assertThat(preAuthorize.value()).isEqualTo("twentythree");
} }
@Test @Test
void synthesizeWhenInheritingInterfaceAndMethodAnnotationsThenResolves() throws Exception { void scanWhenInheritingInterfaceAndMethodAnnotationsThenResolves() throws Exception {
Method method = InheritingInterfaceAndMethodAnnotations.class.getDeclaredMethod("method"); Method method = InheritingInterfaceAndMethodAnnotations.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("three"); assertThat(preAuthorize.value()).isEqualTo("three");
} }
@Test @Test
void synthesizeWhenClassOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception { void scanWhenClassOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception {
Method method = ClassOverridingInterfaceAndMethodInheritance.class.getDeclaredMethod("method"); Method method = ClassOverridingInterfaceAndMethodInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("three"); assertThat(preAuthorize.value()).isEqualTo("three");
} }
@Test @Test
void synthesizeWhenMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception { void scanWhenMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception {
Method method = MethodOverridingInterfaceAndMethodInheritance.class.getDeclaredMethod("method"); Method method = MethodOverridingInterfaceAndMethodInheritance.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twentysix"); assertThat(preAuthorize.value()).isEqualTo("twentysix");
} }
@Test @Test
void synthesizeWhenMultipleMethodInheritanceThenException() throws Exception { void scanWhenMultipleMethodInheritanceThenException() throws Exception {
Method method = MultipleMethodInheritance.class.getDeclaredMethod("method"); Method method = MultipleMethodInheritance.class.getDeclaredMethod("method");
assertThatExceptionOfType(AnnotationConfigurationException.class) assertThatExceptionOfType(AnnotationConfigurationException.class)
.isThrownBy(() -> this.synthesizer.synthesize(method, method.getDeclaringClass())); .isThrownBy(() -> this.scanner.scan(method, method.getDeclaringClass()));
} }
// gh-13234 // gh-13234
@Test @Test
void synthesizeWhenClassInheritingInterfaceAnnotationThenResolves() throws Exception { void scanWhenClassInheritingInterfaceAnnotationThenResolves() throws Exception {
Method method = ClassInheritingInterfaceMethodAnnotation.class.getDeclaredMethod("method"); Method method = ClassInheritingInterfaceMethodAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("three"); assertThat(preAuthorize.value()).isEqualTo("three");
} }
@Test @Test
void synthesizeWhenMethodInheritingMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception { void scanWhenMethodInheritingMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception {
Method method = MethodInheritingMethodOverridingInterfaceAndMethodInheritance.class.getMethod("method"); Method method = MethodInheritingMethodOverridingInterfaceAndMethodInheritance.class.getMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twentysix"); assertThat(preAuthorize.value()).isEqualTo("twentysix");
} }
@Test @Test
void synthesizeWhenClassOverridingMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception { void scanWhenClassOverridingMethodOverridingInterfaceAndMethodInheritanceThenResolves() throws Exception {
Method method = ClassOverridingMethodOverridingInterfaceAndMethodInheritance.class.getMethod("method"); Method method = ClassOverridingMethodOverridingInterfaceAndMethodInheritance.class.getMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, PreAuthorize preAuthorize = this.scanner.scan(method,
ClassOverridingMethodOverridingInterfaceAndMethodInheritance.class); ClassOverridingMethodOverridingInterfaceAndMethodInheritance.class);
assertThat(preAuthorize.value()).isEqualTo("twentysix"); assertThat(preAuthorize.value()).isEqualTo("twentysix");
} }
@Test @Test
void synthesizeWhenInterfaceInheritingAnnotationsAtDifferentLevelsThenException() throws Exception { void scanWhenInterfaceInheritingAnnotationsAtDifferentLevelsThenException() throws Exception {
Method method = InterfaceInheritingAnnotationsAtDifferentLevels.class.getMethod("method"); Method method = InterfaceInheritingAnnotationsAtDifferentLevels.class.getMethod("method");
assertThatExceptionOfType(AnnotationConfigurationException.class) assertThatExceptionOfType(AnnotationConfigurationException.class)
.isThrownBy(() -> this.synthesizer.synthesize(method, method.getDeclaringClass())); .isThrownBy(() -> this.scanner.scan(method, method.getDeclaringClass()));
} }
@Test @Test
void synthesizeWhenClassMethodOverridingAnnotationOnMethodThenResolves() throws Exception { void scanWhenClassMethodOverridingAnnotationOnMethodThenResolves() throws Exception {
Method method = ClassMethodOverridingAnnotationOnMethod.class.getDeclaredMethod("method"); Method method = ClassMethodOverridingAnnotationOnMethod.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("twentyeight"); assertThat(preAuthorize.value()).isEqualTo("twentyeight");
} }
// gh-13490 // gh-13490
@Test @Test
void synthesizeWhenClassInheritingInterfaceInheritingInterfaceMethodAnnotationThenResolves() throws Exception { void scanWhenClassInheritingInterfaceInheritingInterfaceMethodAnnotationThenResolves() throws Exception {
Method method = ClassInheritingInterfaceInheritingInterfaceMethodAnnotation.class.getDeclaredMethod("method"); Method method = ClassInheritingInterfaceInheritingInterfaceMethodAnnotation.class.getDeclaredMethod("method");
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, method.getDeclaringClass()); PreAuthorize preAuthorize = this.scanner.scan(method, method.getDeclaringClass());
assertThat(preAuthorize.value()).isEqualTo("three"); assertThat(preAuthorize.value()).isEqualTo("three");
} }
// gh-15352 // gh-15352
@Test @Test
void synthesizeWhenClassInheritingAbstractClassNoAnnotationsThenNoAnnotation() throws Exception { void scanWhenClassInheritingAbstractClassNoAnnotationsThenNoAnnotation() throws Exception {
Method method = ClassInheritingAbstractClassNoAnnotations.class.getMethod("otherMethod"); Method method = ClassInheritingAbstractClassNoAnnotations.class.getMethod("otherMethod");
Class<?> targetClass = ClassInheritingAbstractClassNoAnnotations.class; Class<?> targetClass = ClassInheritingAbstractClassNoAnnotations.class;
PreAuthorize preAuthorize = this.synthesizer.synthesize(method, targetClass); PreAuthorize preAuthorize = this.scanner.scan(method, targetClass);
assertThat(preAuthorize).isNull(); assertThat(preAuthorize).isNull();
} }

View File

@ -28,10 +28,10 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -99,7 +99,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<AuthenticationPrincipal> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<AuthenticationPrincipal> scanner = SecurityAnnotationScanners
.requireUnique(AuthenticationPrincipal.class); .requireUnique(AuthenticationPrincipal.class);
@Override @Override
@ -153,7 +153,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(AuthenticationPrincipal.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(AuthenticationPrincipal.class, templateDefaults);
} }
/** /**
@ -165,7 +165,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -35,10 +35,10 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -103,7 +103,7 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<AuthenticationPrincipal> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<AuthenticationPrincipal> scanner = SecurityAnnotationScanners
.requireUnique(AuthenticationPrincipal.class); .requireUnique(AuthenticationPrincipal.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -194,7 +194,7 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(AuthenticationPrincipal.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(AuthenticationPrincipal.class, templateDefaults);
} }
/** /**
@ -206,7 +206,7 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -35,10 +35,10 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.CurrentSecurityContext; import org.springframework.security.core.annotation.CurrentSecurityContext;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -101,7 +101,7 @@ public class CurrentSecurityContextArgumentResolver implements HandlerMethodArgu
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<CurrentSecurityContext> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<CurrentSecurityContext> scanner = SecurityAnnotationScanners
.requireUnique(CurrentSecurityContext.class); .requireUnique(CurrentSecurityContext.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -212,7 +212,7 @@ public class CurrentSecurityContextArgumentResolver implements HandlerMethodArgu
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(CurrentSecurityContext.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(CurrentSecurityContext.class, templateDefaults);
} }
/** /**
@ -223,7 +223,7 @@ public class CurrentSecurityContextArgumentResolver implements HandlerMethodArgu
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -27,10 +27,10 @@ import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -102,7 +102,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<AuthenticationPrincipal> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<AuthenticationPrincipal> scanner = SecurityAnnotationScanners
.requireUnique(AuthenticationPrincipal.class); .requireUnique(AuthenticationPrincipal.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -168,7 +168,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(AuthenticationPrincipal.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(AuthenticationPrincipal.class, templateDefaults);
} }
/** /**
@ -180,7 +180,7 @@ public final class AuthenticationPrincipalArgumentResolver implements HandlerMet
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -26,10 +26,10 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.CurrentSecurityContext; import org.springframework.security.core.annotation.CurrentSecurityContext;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.core.context.SecurityContextHolderStrategy;
@ -88,7 +88,7 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<CurrentSecurityContext> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<CurrentSecurityContext> scanner = SecurityAnnotationScanners
.requireUnique(CurrentSecurityContext.class); .requireUnique(CurrentSecurityContext.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -144,7 +144,7 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(CurrentSecurityContext.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(CurrentSecurityContext.class, templateDefaults);
} }
private Object resolveSecurityContextFromAnnotation(MethodParameter parameter, CurrentSecurityContext annotation, private Object resolveSecurityContextFromAnnotation(MethodParameter parameter, CurrentSecurityContext annotation,
@ -178,7 +178,7 @@ public final class CurrentSecurityContextArgumentResolver implements HandlerMeth
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -32,10 +32,10 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -57,7 +57,7 @@ public class AuthenticationPrincipalArgumentResolver extends HandlerMethodArgume
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<AuthenticationPrincipal> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<AuthenticationPrincipal> scanner = SecurityAnnotationScanners
.requireUnique(AuthenticationPrincipal.class); .requireUnique(AuthenticationPrincipal.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -138,7 +138,7 @@ public class AuthenticationPrincipalArgumentResolver extends HandlerMethodArgume
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(AuthenticationPrincipal.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(AuthenticationPrincipal.class, templateDefaults);
} }
/** /**
@ -150,7 +150,7 @@ public class AuthenticationPrincipalArgumentResolver extends HandlerMethodArgume
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }

View File

@ -32,10 +32,10 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.security.core.annotation.AnnotationSynthesizer;
import org.springframework.security.core.annotation.AnnotationSynthesizers;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults; import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.security.core.annotation.CurrentSecurityContext; import org.springframework.security.core.annotation.CurrentSecurityContext;
import org.springframework.security.core.annotation.SecurityAnnotationScanner;
import org.springframework.security.core.annotation.SecurityAnnotationScanners;
import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -57,7 +57,7 @@ public class CurrentSecurityContextArgumentResolver extends HandlerMethodArgumen
private ExpressionParser parser = new SpelExpressionParser(); private ExpressionParser parser = new SpelExpressionParser();
private AnnotationSynthesizer<CurrentSecurityContext> synthesizer = AnnotationSynthesizers private SecurityAnnotationScanner<CurrentSecurityContext> scanner = SecurityAnnotationScanners
.requireUnique(CurrentSecurityContext.class); .requireUnique(CurrentSecurityContext.class);
private BeanResolver beanResolver; private BeanResolver beanResolver;
@ -85,7 +85,7 @@ public class CurrentSecurityContextArgumentResolver extends HandlerMethodArgumen
* @since 6.4 * @since 6.4
*/ */
public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) { public void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.synthesizer = AnnotationSynthesizers.requireUnique(CurrentSecurityContext.class, templateDefaults); this.scanner = SecurityAnnotationScanners.requireUnique(CurrentSecurityContext.class, templateDefaults);
} }
@Override @Override
@ -190,7 +190,7 @@ public class CurrentSecurityContextArgumentResolver extends HandlerMethodArgumen
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) { private <T extends Annotation> T findMethodAnnotation(MethodParameter parameter) {
return (T) this.cachedAttributes.computeIfAbsent(parameter, return (T) this.cachedAttributes.computeIfAbsent(parameter,
(methodParameter) -> this.synthesizer.synthesize(methodParameter.getParameter())); (methodParameter) -> this.scanner.scan(methodParameter.getParameter()));
} }
} }