Polish SecurityNamespaceHandler Version Checking

PR gh-17689
This commit is contained in:
Josh Cummings 2025-08-15 17:26:57 -06:00
parent 01401f1c67
commit 890c11d428
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
2 changed files with 39 additions and 11 deletions

View File

@ -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

View File

@ -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> classUtils;
@Test
public void constructionSucceeds() {
public void constructionWhenVersionsMatchThenLogsNothing() {
Appender<ILoggingEvent> 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<ILoggingEvent> appender = mock(Appender.class);
Logger logger = (Logger) LoggerFactory.getLogger(SecurityNamespaceHandler.class);
logger.addAppender(appender);
try (MockedStatic<SpringSecurityCoreVersion> core = Mockito.mockStatic(SpringSecurityCoreVersion.class)) {
core.when(SpringSecurityCoreVersion::getVersion).thenReturn("mismatching");
assertThat(new SecurityNamespaceHandler()).isNotNull();
ArgumentCaptor<ILoggingEvent> captor = ArgumentCaptor.forClass(ILoggingEvent.class);
verify(appender).doAppend(captor.capture());
assertThat(captor.getValue().getLevel()).isEqualTo(Level.ERROR);
}
}
@Test