ソースを参照

Deprecate PrePostTemplateDefaults

Since there is nothing specific to configuring pre/post
annotations, there is no need for the extra class.

If a need like this does arise in the future,
either AnnotationTemplateExpressionDefaults can be sub-
classed, or it can have introduced a Map field holding
custom properties.

Issue gh-15286
Josh Cummings 1 年間 前
コミット
e40c98e6d7
13 ファイル変更173 行追加35 行削除
  1. 9 0
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java
  2. 53 26
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java
  3. 10 0
      core/src/main/java/org/springframework/security/authorization/method/AbstractExpressionAttributeRegistry.java
  4. 16 0
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java
  5. 2 1
      core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeExpressionAttributeRegistry.java
  6. 15 0
      core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java
  7. 2 1
      core/src/main/java/org/springframework/security/authorization/method/PostFilterExpressionAttributeRegistry.java
  8. 16 0
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java
  9. 2 1
      core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeExpressionAttributeRegistry.java
  10. 16 0
      core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java
  11. 2 1
      core/src/main/java/org/springframework/security/authorization/method/PreFilterExpressionAttributeRegistry.java
  12. 26 1
      core/src/main/java/org/springframework/security/authorization/method/PrePostTemplateDefaults.java
  13. 4 4
      docs/modules/ROOT/pages/servlet/authorization/method-security.adoc

+ 9 - 0
config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

@@ -51,6 +51,7 @@ import org.springframework.security.authorization.method.PreAuthorizeAuthorizati
 import org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor;
 import org.springframework.security.authorization.method.PrePostTemplateDefaults;
 import org.springframework.security.config.core.GrantedAuthorityDefaults;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.util.function.SingletonSupplier;
 
@@ -72,6 +73,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor preFilterAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
+			ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
 			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
@@ -80,6 +82,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 		PreFilterAuthorizationMethodInterceptor preFilter = new PreFilterAuthorizationMethodInterceptor();
 		preFilter.setOrder(preFilter.getOrder() + configuration.interceptorOrderOffset);
 		return new DeferringMethodInterceptor<>(preFilter, (f) -> {
+			templateExpressionDefaultsProvider.ifAvailable(f::setTemplateDefaults);
 			methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
 			f.setExpressionHandler(expressionHandlerProvider
 				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
@@ -91,6 +94,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor preAuthorizeAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
+			ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
 			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
@@ -103,6 +107,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 			.preAuthorize(manager(manager, registryProvider));
 		preAuthorize.setOrder(preAuthorize.getOrder() + configuration.interceptorOrderOffset);
 		return new DeferringMethodInterceptor<>(preAuthorize, (f) -> {
+			templateExpressionDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
 			methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
 			manager.setExpressionHandler(expressionHandlerProvider
 				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
@@ -115,6 +120,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor postAuthorizeAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
+			ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
 			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
@@ -127,6 +133,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 			.postAuthorize(manager(manager, registryProvider));
 		postAuthorize.setOrder(postAuthorize.getOrder() + configuration.interceptorOrderOffset);
 		return new DeferringMethodInterceptor<>(postAuthorize, (f) -> {
+			templateExpressionDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
 			methodSecurityDefaultsProvider.ifAvailable(manager::setTemplateDefaults);
 			manager.setExpressionHandler(expressionHandlerProvider
 				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));
@@ -139,6 +146,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 	static MethodInterceptor postFilterAuthorizationMethodInterceptor(
 			ObjectProvider<GrantedAuthorityDefaults> defaultsProvider,
+			ObjectProvider<AnnotationTemplateExpressionDefaults> templateExpressionDefaultsProvider,
 			ObjectProvider<PrePostTemplateDefaults> methodSecurityDefaultsProvider,
 			ObjectProvider<MethodSecurityExpressionHandler> expressionHandlerProvider,
 			ObjectProvider<SecurityContextHolderStrategy> strategyProvider,
@@ -147,6 +155,7 @@ final class PrePostMethodSecurityConfiguration implements ImportAware, AopInfras
 		PostFilterAuthorizationMethodInterceptor postFilter = new PostFilterAuthorizationMethodInterceptor();
 		postFilter.setOrder(postFilter.getOrder() + configuration.interceptorOrderOffset);
 		return new DeferringMethodInterceptor<>(postFilter, (f) -> {
+			templateExpressionDefaultsProvider.ifAvailable(f::setTemplateDefaults);
 			methodSecurityDefaultsProvider.ifAvailable(f::setTemplateDefaults);
 			f.setExpressionHandler(expressionHandlerProvider
 				.getIfAvailable(() -> defaultExpressionHandler(defaultsProvider, roleHierarchyProvider, context)));

+ 53 - 26
config/src/test/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfigurationTests.java

@@ -33,6 +33,8 @@ import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import org.springframework.aop.Advisor;
 import org.springframework.aop.support.DefaultPointcutAdvisor;
@@ -78,6 +80,7 @@ import org.springframework.security.config.test.SpringTestContext;
 import org.springframework.security.config.test.SpringTestContextExtension;
 import org.springframework.security.config.test.SpringTestParentApplicationContextExecutionListener;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.security.test.context.support.WithAnonymousUser;
 import org.springframework.security.test.context.support.WithMockUser;
@@ -607,69 +610,77 @@ public class PrePostMethodSecurityConfigurationTests {
 		assertThat(filtered).containsExactly("DoNotDrop");
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser
-	public void methodeWhenParameterizedPreAuthorizeMetaAnnotationThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodeWhenParameterizedPreAuthorizeMetaAnnotationThenPasses(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.hasRole("USER")).isTrue();
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser
-	public void methodRoleWhenPreAuthorizeMetaAnnotationHardcodedParameterThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodRoleWhenPreAuthorizeMetaAnnotationHardcodedParameterThenPasses(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.hasUserRole()).isTrue();
 	}
 
-	@Test
-	public void methodWhenParameterizedAnnotationThenFails() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
+	public void methodWhenParameterizedAnnotationThenFails(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThatExceptionOfType(IllegalArgumentException.class)
 			.isThrownBy(service::placeholdersOnlyResolvedByMetaAnnotations);
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser(authorities = "SCOPE_message:read")
-	public void methodWhenMultiplePlaceholdersHasAuthorityThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodWhenMultiplePlaceholdersHasAuthorityThenPasses(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.readMessage()).isEqualTo("message");
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser(roles = "ADMIN")
-	public void methodWhenMultiplePlaceholdersHasRoleThenPasses() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodWhenMultiplePlaceholdersHasRoleThenPasses(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.readMessage()).isEqualTo("message");
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser
-	public void methodWhenPostAuthorizeMetaAnnotationThenAuthorizes() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodWhenPostAuthorizeMetaAnnotationThenAuthorizes(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		service.startsWithDave("daveMatthews");
 		assertThatExceptionOfType(AccessDeniedException.class)
 			.isThrownBy(() -> service.startsWithDave("jenniferHarper"));
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser
-	public void methodWhenPreFilterMetaAnnotationThenFilters() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodWhenPreFilterMetaAnnotationThenFilters(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.parametersContainDave(new ArrayList<>(List.of("dave", "carla", "vanessa", "paul"))))
 			.containsExactly("dave");
 	}
 
-	@Test
+	@ParameterizedTest
+	@ValueSource(classes = { LegacyMetaAnnotationPlaceholderConfig.class, MetaAnnotationPlaceholderConfig.class })
 	@WithMockUser
-	public void methodWhenPostFilterMetaAnnotationThenFilters() {
-		this.spring.register(MetaAnnotationPlaceholderConfig.class).autowire();
+	public void methodWhenPostFilterMetaAnnotationThenFilters(Class<?> config) {
+		this.spring.register(config).autowire();
 		MetaAnnotationService service = this.spring.getContext().getBean(MetaAnnotationService.class);
 		assertThat(service.resultsContainDave(new ArrayList<>(List.of("dave", "carla", "vanessa", "paul"))))
 			.containsExactly("dave");
@@ -827,7 +838,7 @@ public class PrePostMethodSecurityConfigurationTests {
 	@WithMockUser
 	void postAuthorizeWhenNullDeniedMetaAnnotationThanWorks() {
 		this.spring
-			.register(MethodSecurityServiceEnabledConfig.class, MetaAnnotationPlaceholderConfig.class,
+			.register(MethodSecurityServiceEnabledConfig.class, LegacyMetaAnnotationPlaceholderConfig.class,
 					MethodSecurityService.NullPostProcessor.class)
 			.autowire();
 		MethodSecurityService service = this.spring.getContext().getBean(MethodSecurityService.class);
@@ -1268,7 +1279,7 @@ public class PrePostMethodSecurityConfigurationTests {
 
 	@Configuration
 	@EnableMethodSecurity
-	static class MetaAnnotationPlaceholderConfig {
+	static class LegacyMetaAnnotationPlaceholderConfig {
 
 		@Bean
 		PrePostTemplateDefaults methodSecurityDefaults() {
@@ -1282,6 +1293,22 @@ public class PrePostMethodSecurityConfigurationTests {
 
 	}
 
+	@Configuration
+	@EnableMethodSecurity
+	static class MetaAnnotationPlaceholderConfig {
+
+		@Bean
+		AnnotationTemplateExpressionDefaults methodSecurityDefaults() {
+			return new AnnotationTemplateExpressionDefaults();
+		}
+
+		@Bean
+		MetaAnnotationService metaAnnotationService() {
+			return new MetaAnnotationService();
+		}
+
+	}
+
 	static class MetaAnnotationService {
 
 		@RequireRole(role = "#role")

+ 10 - 0
core/src/main/java/org/springframework/security/authorization/method/AbstractExpressionAttributeRegistry.java

@@ -26,6 +26,7 @@ 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.security.core.annotation.AnnotationTemplateExpressionDefaults;
 import org.springframework.util.Assert;
 
 /**
@@ -76,6 +77,15 @@ abstract class AbstractExpressionAttributeRegistry<T extends ExpressionAttribute
 		this.expressionHandler = expressionHandler;
 	}
 
+	@Deprecated
+	void setTemplateDefaults(PrePostTemplateDefaults defaults) {
+		AnnotationTemplateExpressionDefaults adapter = new AnnotationTemplateExpressionDefaults();
+		adapter.setIgnoreUnknown(defaults.isIgnoreUnknown());
+		setTemplateDefaults(adapter);
+	}
+
+	abstract void setTemplateDefaults(AnnotationTemplateExpressionDefaults adapter);
+
 	/**
 	 * Subclasses should implement this method to provide the non-null
 	 * {@link ExpressionAttribute} for the method and the target class.

+ 16 - 0
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeAuthorizationManager.java

@@ -28,6 +28,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.AuthorizationResult;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 
 /**
  * An {@link AuthorizationManager} which can determine if an {@link Authentication} may
@@ -57,11 +58,26 @@ public final class PostAuthorizeAuthorizationManager
 	 * not be resolved.
 	 * @param defaults - whether to resolve pre/post-authorization templates parameters
 	 * @since 6.3
+	 * @deprecated Please use
+	 * {@link #setTemplateDefaults(AnnotationTemplateExpressionDefaults)} instead
 	 */
+	@Deprecated
 	public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
 		this.registry.setTemplateDefaults(defaults);
 	}
 
+	/**
+	 * 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.4
+	 */
+	public void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
+		this.registry.setTemplateDefaults(defaults);
+	}
+
 	/**
 	 * Invokes
 	 * {@link PostAuthorizeExpressionAttributeRegistry#setApplicationContext(ApplicationContext)}

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/method/PostAuthorizeExpressionAttributeRegistry.java

@@ -27,6 +27,7 @@ import org.springframework.expression.Expression;
 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.util.Assert;
 
 /**
@@ -90,7 +91,7 @@ final class PostAuthorizeExpressionAttributeRegistry extends AbstractExpressionA
 		this.handlerResolver = (clazz) -> resolveHandler(context, clazz);
 	}
 
-	void setTemplateDefaults(PrePostTemplateDefaults templateDefaults) {
+	void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
 		this.postAuthorizeSynthesizer = AnnotationSynthesizers.requireUnique(PostAuthorize.class, templateDefaults);
 	}
 

+ 15 - 0
core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java

@@ -28,6 +28,7 @@ import org.springframework.security.access.expression.method.MethodSecurityExpre
 import org.springframework.security.access.prepost.PostFilter;
 import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 
@@ -73,11 +74,25 @@ public final class PostFilterAuthorizationMethodInterceptor implements Authoriza
 	 * not be resolved.
 	 * @param defaults - whether to resolve pre/post-authorization templates parameters
 	 * @since 6.3
+	 * @deprecated Please use {@link AnnotationTemplateExpressionDefaults} instead
 	 */
+	@Deprecated
 	public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
 		this.registry.setTemplateDefaults(defaults);
 	}
 
+	/**
+	 * 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.4
+	 */
+	public void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
+		this.registry.setTemplateDefaults(defaults);
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/method/PostFilterExpressionAttributeRegistry.java

@@ -23,6 +23,7 @@ import org.springframework.lang.NonNull;
 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;
 
 /**
  * For internal use only, as this contract is likely to change.
@@ -47,7 +48,7 @@ final class PostFilterExpressionAttributeRegistry extends AbstractExpressionAttr
 		return new ExpressionAttribute(postFilterExpression);
 	}
 
-	void setTemplateDefaults(PrePostTemplateDefaults defaults) {
+	void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
 		this.synthesizer = AnnotationSynthesizers.requireUnique(PostFilter.class, defaults);
 	}
 

+ 16 - 0
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeAuthorizationManager.java

@@ -28,6 +28,7 @@ import org.springframework.security.authorization.AuthorizationDecision;
 import org.springframework.security.authorization.AuthorizationManager;
 import org.springframework.security.authorization.AuthorizationResult;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 
 /**
  * An {@link AuthorizationManager} which can determine if an {@link Authentication} may
@@ -57,11 +58,26 @@ public final class PreAuthorizeAuthorizationManager
 	 * not be resolved.
 	 * @param defaults - whether to resolve pre/post-authorization templates parameters
 	 * @since 6.3
+	 * @deprecated Please use
+	 * {@link #setTemplateDefaults(AnnotationTemplateExpressionDefaults)} instead
 	 */
+	@Deprecated
 	public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
 		this.registry.setTemplateDefaults(defaults);
 	}
 
+	/**
+	 * 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.4
+	 */
+	public void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
+		this.registry.setTemplateDefaults(defaults);
+	}
+
 	public void setApplicationContext(ApplicationContext context) {
 		this.registry.setApplicationContext(context);
 	}

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/method/PreAuthorizeExpressionAttributeRegistry.java

@@ -27,6 +27,7 @@ import org.springframework.expression.Expression;
 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.util.Assert;
 
 /**
@@ -90,7 +91,7 @@ final class PreAuthorizeExpressionAttributeRegistry extends AbstractExpressionAt
 		this.handlerResolver = (clazz) -> resolveHandler(context, clazz);
 	}
 
-	void setTemplateDefaults(PrePostTemplateDefaults defaults) {
+	void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
 		this.preAuthorizeSynthesizer = AnnotationSynthesizers.requireUnique(PreAuthorize.class, defaults);
 	}
 

+ 16 - 0
core/src/main/java/org/springframework/security/authorization/method/PreFilterAuthorizationMethodInterceptor.java

@@ -28,6 +28,7 @@ import org.springframework.security.access.expression.method.MethodSecurityExpre
 import org.springframework.security.access.prepost.PreFilter;
 import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.util.Assert;
@@ -74,11 +75,26 @@ public final class PreFilterAuthorizationMethodInterceptor implements Authorizat
 	 * not be resolved.
 	 * @param defaults - whether to resolve pre/post-authorization templates parameters
 	 * @since 6.3
+	 * @deprecated Please use
+	 * {@link #setTemplateDefaults(AnnotationTemplateExpressionDefaults)} instead
 	 */
+	@Deprecated
 	public void setTemplateDefaults(PrePostTemplateDefaults defaults) {
 		this.registry.setTemplateDefaults(defaults);
 	}
 
+	/**
+	 * 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.4
+	 */
+	public void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
+		this.registry.setTemplateDefaults(defaults);
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */

+ 2 - 1
core/src/main/java/org/springframework/security/authorization/method/PreFilterExpressionAttributeRegistry.java

@@ -23,6 +23,7 @@ import org.springframework.lang.NonNull;
 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;
 
 /**
  * For internal use only, as this contract is likely to change.
@@ -48,7 +49,7 @@ final class PreFilterExpressionAttributeRegistry
 		return new PreFilterExpressionAttribute(preFilterExpression, preFilter.filterTarget());
 	}
 
-	void setTemplateDefaults(PrePostTemplateDefaults defaults) {
+	void setTemplateDefaults(AnnotationTemplateExpressionDefaults defaults) {
 		this.synthesizer = AnnotationSynthesizers.requireUnique(PreFilter.class, defaults);
 	}
 

+ 26 - 1
core/src/main/java/org/springframework/security/authorization/method/PrePostTemplateDefaults.java

@@ -27,7 +27,32 @@ import org.springframework.security.core.annotation.AnnotationTemplateExpression
  * @see org.springframework.security.access.prepost.PostAuthorize
  * @see org.springframework.security.access.prepost.PreFilter
  * @see org.springframework.security.access.prepost.PostFilter
+ * @deprecated Please use {@link AnnotationTemplateExpressionDefaults} instead
  */
-public final class PrePostTemplateDefaults extends AnnotationTemplateExpressionDefaults {
+@Deprecated
+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>.
+	 */
+	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
+	 */
+	public void setIgnoreUnknown(boolean ignoreUnknown) {
+		this.ignoreUnknown = ignoreUnknown;
+	}
 
 }

+ 4 - 4
docs/modules/ROOT/pages/servlet/authorization/method-security.adoc

@@ -1012,8 +1012,8 @@ Java::
 [source,java,role="primary"]
 ----
 @Bean
-static PrePostTemplateDefaults prePostTemplateDefaults() {
-	return new PrePostTemplateDefaults();
+static AnnotationTemplateExpressionDefaults templateExpressionDefaults() {
+	return new AnnotationTemplateExpressionDefaults();
 }
 ----
 
@@ -1023,8 +1023,8 @@ Kotlin::
 ----
 companion object {
     @Bean
-    fun prePostTemplateDefaults(): PrePostTemplateDefaults {
-        return PrePostTemplateDefaults()
+    fun templateExpressionDefaults(): AnnotationTemplateExpressionDefaults {
+        return AnnotationTemplateExpressionDefaults()
     }
 }
 ----