From 1eef373ca0c68999ef633f58505afed2a322ae42 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:29:28 -0600 Subject: [PATCH] Improve Error Message for Invalid JSR-250 Usage This commit adds an IllegalStateException guard when spring-security-access is missing and the application is using @EnableGlobalMethodSecurity with jsr250Enabled. Issue gh-19441 Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com> --- .../GlobalMethodSecuritySelector.java | 23 ++++++++++--------- .../method/configuration/Gh19441Tests.java | 17 ++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java index 099c852cf3..e71fb9b060 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java @@ -39,7 +39,8 @@ import org.springframework.util.ClassUtils; @Deprecated final class GlobalMethodSecuritySelector implements ImportSelector { - private static final String METHOD_SECURITY_METADATA_SOURCE_ADVISOR = "org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor"; + private static final boolean isAccessPresent = ClassUtils.isPresent( + "org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor", null); @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { @@ -59,28 +60,28 @@ final class GlobalMethodSecuritySelector implements ImportSelector { String autoProxyClassName = isProxy ? AutoProxyRegistrar.class.getName() : GlobalMethodSecurityAspectJAutoProxyRegistrar.class.getName(); boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); - if (isProxy || !skipMethodSecurityConfiguration) { - // The proxy-mode advisor registrar and GlobalMethodSecurityConfiguration - // (imported for both proxy and aspectj modes) need types that only exist in - // the optional spring-security-access module. - Assert.state( - ClassUtils.isPresent(METHOD_SECURITY_METADATA_SOURCE_ADVISOR, ClassUtils.getDefaultClassLoader()), - () -> "@EnableGlobalMethodSecurity requires the spring-security-access dependency on the " - + "classpath. Please add spring-security-access, or migrate to @EnableMethodSecurity " - + "which does not require it."); - } List classNames = new ArrayList<>(4); if (isProxy) { + assertAccessModulePresent(); classNames.add(MethodSecurityMetadataSourceAdvisorRegistrar.class.getName()); } classNames.add(autoProxyClassName); if (!skipMethodSecurityConfiguration) { + assertAccessModulePresent(); classNames.add(GlobalMethodSecurityConfiguration.class.getName()); } if (jsr250Enabled) { + assertAccessModulePresent(); classNames.add(Jsr250MetadataSourceConfiguration.class.getName()); } return classNames.toArray(new String[0]); } + private static void assertAccessModulePresent() { + Assert.state(isAccessPresent, + () -> "@EnableGlobalMethodSecurity requires the spring-security-access dependency on the " + + "classpath. Please add spring-security-access, or migrate to @EnableMethodSecurity " + + "which does not require it."); + } + } diff --git a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Gh19441Tests.java b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Gh19441Tests.java index 2e02a25ff5..857122c14c 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Gh19441Tests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/method/configuration/Gh19441Tests.java @@ -88,6 +88,17 @@ public class Gh19441Tests { } } + @Test + public void enableGlobalMethodSecurityWhenAspectJModeAndJsr250EnabledAndConfigurationSubclassedAndAccessModuleAbsentThenClearException() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { + context.register(EnableGlobalMethodSecurityAspectJJsr250SubclassedConfig.class); + assertThatExceptionOfType(Exception.class).isThrownBy(context::refresh) + .havingRootCause() + .isInstanceOf(IllegalStateException.class) + .withMessageContaining("spring-security-access"); + } + } + @Configuration @EnableMethodSecurity static class EnableMethodSecurityConfig { @@ -118,4 +129,10 @@ public class Gh19441Tests { } + @Configuration + @EnableGlobalMethodSecurity(jsr250Enabled = true, mode = AdviceMode.ASPECTJ) + static class EnableGlobalMethodSecurityAspectJJsr250SubclassedConfig extends GlobalMethodSecurityConfiguration { + + } + }