diff --git a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java index 0cff79d85d..58d8592338 100644 --- a/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java +++ b/config/src/main/java/org/springframework/security/config/SecurityNamespaceHandler.java @@ -18,6 +18,7 @@ package org.springframework.security.config; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -77,17 +78,16 @@ public final class SecurityNamespaceHandler implements NamespaceHandler { public SecurityNamespaceHandler() { String coreVersion = SpringSecurityCoreVersion.getVersion(); + String configVersion = configVersion(); + if (!Objects.equals(coreVersion, configVersion)) { + String message = "You are attempting to run spring-security-core:%s with spring-security-config:%s"; + this.logger.error(String.format(message, coreVersion, configVersion)); + } + } + + private static String configVersion() { Package pkg = SpringSecurityCoreVersion.class.getPackage(); - if (pkg == null || coreVersion == null) { - this.logger.info("Couldn't determine package version information."); - return; - } - String version = pkg.getImplementationVersion(); - this.logger.info("Spring Security 'config' module version is " + version); - if (version.compareTo(coreVersion) != 0) { - this.logger - .error("You are running with different versions of the Spring Security 'core' and 'config' modules"); - } + return (pkg != null) ? pkg.getImplementationVersion() : null; } @Override diff --git a/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java b/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java index c4be43c569..1d9740a925 100644 --- a/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java +++ b/config/src/test/java/org/springframework/security/config/SecurityNamespaceHandlerTests.java @@ -16,17 +16,25 @@ package org.springframework.security.config; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; import org.apache.commons.logging.Log; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Answers; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockedStatic; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.security.config.util.InMemoryXmlApplicationContext; import org.springframework.security.config.util.SpringSecurityVersions; +import org.springframework.security.core.SpringSecurityCoreVersion; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.ClassUtils; @@ -35,6 +43,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; /** @@ -63,8 +73,26 @@ public class SecurityNamespaceHandlerTests { private MockedStatic classUtils; @Test - public void constructionSucceeds() { + public void constructionWhenVersionsMatchThenLogsNothing() { + Appender appender = mock(Appender.class); + Logger logger = (Logger) LoggerFactory.getLogger(SecurityNamespaceHandler.class); + logger.addAppender(appender); assertThat(new SecurityNamespaceHandler()).isNotNull(); + verify(appender, never()).doAppend(any(ILoggingEvent.class)); + } + + @Test + public void constructorWhenDetectsMismatchingVersionsThenLogsError() { + Appender appender = mock(Appender.class); + Logger logger = (Logger) LoggerFactory.getLogger(SecurityNamespaceHandler.class); + logger.addAppender(appender); + try (MockedStatic core = Mockito.mockStatic(SpringSecurityCoreVersion.class)) { + core.when(SpringSecurityCoreVersion::getVersion).thenReturn("mismatching"); + assertThat(new SecurityNamespaceHandler()).isNotNull(); + ArgumentCaptor captor = ArgumentCaptor.forClass(ILoggingEvent.class); + verify(appender).doAppend(captor.capture()); + assertThat(captor.getValue().getLevel()).isEqualTo(Level.ERROR); + } } @Test