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
This commit is contained in:
Josh Cummings 2024-08-09 13:28:36 -06:00
parent 2c02d8aec7
commit e40c98e6d7
13 changed files with 173 additions and 35 deletions

View File

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

View File

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

View File

@ -26,6 +26,7 @@ import org.springframework.core.MethodClassKey;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -76,6 +77,15 @@ abstract class AbstractExpressionAttributeRegistry<T extends ExpressionAttribute
this.expressionHandler = expressionHandler; 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 * Subclasses should implement this method to provide the non-null
* {@link ExpressionAttribute} for the method and the target class. * {@link ExpressionAttribute} for the method and the target class.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,32 @@ import org.springframework.security.core.annotation.AnnotationTemplateExpression
* @see org.springframework.security.access.prepost.PostAuthorize * @see org.springframework.security.access.prepost.PostAuthorize
* @see org.springframework.security.access.prepost.PreFilter * @see org.springframework.security.access.prepost.PreFilter
* @see org.springframework.security.access.prepost.PostFilter * @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;
}
} }

View File

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