Prefer file resolution when loading SSL content

Update `SslAutoConfiguration` so that the used resource loader prefers
file based resolution when paths are specified without a prefix. This
restores the behavior found in Spring Boot 3.3.

The `ApplicationResourceLoader` has been updated with a new `get` method
that accepts a `preferFileResolution` parameter. Unfortunately, we can't
directly influence the resource returned by the delegate
`ResourceLoader` since we can't override `getResourceByPath(...)`.
Instead we check if the returned type was likely to have been created
by a call to that method. If so, we change it to a `FileSystemResource`.

This approach should hopefully work with `DefaultResourceLoader` and
subclasses.

Fixes gh-43274
This commit is contained in:
Phillip Webb
2024-12-03 14:46:13 -08:00
parent 7a4e071709
commit 3ddfd62f16
4 changed files with 126 additions and 5 deletions

View File

@@ -43,7 +43,7 @@ public class SslAutoConfiguration {
private final SslProperties sslProperties;
SslAutoConfiguration(ResourceLoader resourceLoader, SslProperties sslProperties) {
this.resourceLoader = ApplicationResourceLoader.get(resourceLoader);
this.resourceLoader = ApplicationResourceLoader.get(resourceLoader, true);
this.sslProperties = sslProperties;
}

View File

@@ -119,6 +119,24 @@ class SslAutoConfigurationTests {
});
}
@Test
void sslBundleWithoutClassPathPrefix() {
List<String> propertyValues = new ArrayList<>();
String location = "src/test/resources/org/springframework/boot/autoconfigure/ssl/";
propertyValues.add("spring.ssl.bundle.pem.test.key.alias=alias1");
propertyValues.add("spring.ssl.bundle.pem.test.key.password=secret1");
propertyValues.add("spring.ssl.bundle.pem.test.keystore.certificate=" + location + "rsa-cert.pem");
propertyValues.add("spring.ssl.bundle.pem.test.keystore.keystore.private-key=" + location + "rsa-key.pem");
propertyValues.add("spring.ssl.bundle.pem.test.truststore.certificate=" + location + "rsa-cert.pem");
this.contextRunner.withPropertyValues(propertyValues.toArray(String[]::new)).run((context) -> {
assertThat(context).hasSingleBean(SslBundles.class);
SslBundles bundles = context.getBean(SslBundles.class);
SslBundle bundle = bundles.getBundle("test");
assertThat(bundle.getStores().getKeyStore().getCertificate("alias1")).isNotNull();
assertThat(bundle.getStores().getTrustStore().getCertificate("ssl")).isNotNull();
});
}
@Configuration
@EnableConfigurationProperties(CustomSslProperties.class)
public static class CustomSslBundleConfiguration {