diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 7a32b64bd4..6c95b16aa4 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -575,7 +575,7 @@ bom { ] } } - library("HttpClient5", "5.3.1") { + library("HttpClient5", "5.4") { group("org.apache.httpcomponents.client5") { modules = [ "httpclient5", diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java index 7a5ee2f7d6..f571a1d973 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/TestRestTemplate.java @@ -38,8 +38,8 @@ import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.http.ssl.TlsSocketStrategy; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.ssl.TLS; @@ -992,7 +992,7 @@ public class TestRestTemplate { ENABLE_REDIRECTS, /** - * Use a {@link SSLConnectionSocketFactory} that trusts self-signed certificates. + * Use a {@link TlsSocketStrategy} that trusts self-signed certificates. */ SSL @@ -1038,7 +1038,7 @@ public class TestRestTemplate { throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create(); if (ssl) { - builder.setSSLSocketFactory(createSocketFactory()); + builder.setTlsSocketStrategy(createTlsSocketStrategy()); } if (readTimeout != null) { SocketConfig socketConfig = SocketConfig.custom() @@ -1049,14 +1049,12 @@ public class TestRestTemplate { return builder.build(); } - private SSLConnectionSocketFactory createSocketFactory() - throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { + private TlsSocketStrategy createTlsSocketStrategy() + throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) .build(); - return SSLConnectionSocketFactoryBuilder.create() - .setSslContext(sslContext) - .setTlsVersions(TLS.V_1_3, TLS.V_1_2) - .build(); + return new DefaultClientTlsStrategy(sslContext, new String[] { TLS.V_1_3.getId(), TLS.V_1_2.getId() }, null, + null, null); } @Override diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/LocalHttpClientTransport.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/LocalHttpClientTransport.java index a097e0f906..67ac077ea0 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/LocalHttpClientTransport.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/LocalHttpClientTransport.java @@ -18,9 +18,8 @@ package org.springframework.boot.buildpack.platform.docker.transport; import java.io.IOException; import java.net.InetAddress; -import java.net.InetSocketAddress; +import java.net.Proxy; import java.net.Socket; -import java.net.UnknownHostException; import com.sun.jna.Platform; import org.apache.hc.client5.http.DnsResolver; @@ -30,12 +29,11 @@ import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator; +import org.apache.hc.client5.http.io.DetachedSocketFactory; import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.routing.HttpRoutePlanner; -import org.apache.hc.client5.http.socket.ConnectionSocketFactory; import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.config.Registry; -import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.util.TimeValue; @@ -48,6 +46,7 @@ import org.springframework.boot.buildpack.platform.socket.UnixDomainSocket; * * @author Phillip Webb * @author Scott Frederick + * @author Moritz Halbritter */ final class LocalHttpClientTransport extends HttpClientTransport { @@ -62,9 +61,9 @@ final class LocalHttpClientTransport extends HttpClientTransport { } static LocalHttpClientTransport create(ResolvedDockerHost dockerHost) { - HttpClientBuilder builder = HttpClients.custom(); - builder.setConnectionManager(new LocalConnectionManager(dockerHost.getAddress())); - builder.setRoutePlanner(new LocalRoutePlanner()); + HttpClientBuilder builder = HttpClients.custom() + .setConnectionManager(new LocalConnectionManager(dockerHost)) + .setRoutePlanner(new LocalRoutePlanner()); HttpHost host = new HttpHost(DOCKER_SCHEME, dockerHost.getAddress()); return new LocalHttpClientTransport(builder.build(), host); } @@ -78,15 +77,34 @@ final class LocalHttpClientTransport extends HttpClientTransport { .setValidateAfterInactivity(TimeValue.NEG_ONE_MILLISECOND) .build(); - LocalConnectionManager(String host) { - super(getRegistry(host), null, null, new LocalDnsResolver()); + LocalConnectionManager(ResolvedDockerHost dockerHost) { + super(new DefaultHttpClientConnectionOperator(new LocalDetachedSocketFactory(dockerHost), null, + new LocalDnsResolver(), (name) -> null), null); setConnectionConfig(CONNECTION_CONFIG); } - private static Registry getRegistry(String host) { - RegistryBuilder builder = RegistryBuilder.create(); - builder.register(DOCKER_SCHEME, new LocalConnectionSocketFactory(host)); - return builder.build(); + } + + /** + * {@link DetachedSocketFactory} for local Docker. + */ + static class LocalDetachedSocketFactory implements DetachedSocketFactory { + + private static final String NPIPE_PREFIX = "npipe://"; + + private final ResolvedDockerHost dockerHost; + + LocalDetachedSocketFactory(ResolvedDockerHost dockerHost) { + this.dockerHost = dockerHost; + } + + @Override + public Socket create(Proxy proxy) throws IOException { + String address = this.dockerHost.getAddress(); + if (address.startsWith(NPIPE_PREFIX)) { + return NamedPipeSocket.get(address.substring(NPIPE_PREFIX.length())); + } + return (!Platform.isWindows()) ? UnixDomainSocket.get(address) : NamedPipeSocket.get(address); } } @@ -99,48 +117,17 @@ final class LocalHttpClientTransport extends HttpClientTransport { private static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress(); @Override - public InetAddress[] resolve(String host) throws UnknownHostException { + public InetAddress[] resolve(String host) { return new InetAddress[] { LOOPBACK }; } @Override - public String resolveCanonicalHostname(String host) throws UnknownHostException { + public String resolveCanonicalHostname(String host) { return LOOPBACK.getCanonicalHostName(); } } - /** - * {@link ConnectionSocketFactory} that connects to the local Docker domain socket or - * named pipe. - */ - private static class LocalConnectionSocketFactory implements ConnectionSocketFactory { - - private static final String NPIPE_PREFIX = "npipe://"; - - private final String host; - - LocalConnectionSocketFactory(String host) { - this.host = host; - } - - @Override - public Socket createSocket(HttpContext context) throws IOException { - if (this.host.startsWith(NPIPE_PREFIX)) { - return NamedPipeSocket.get(this.host.substring(NPIPE_PREFIX.length())); - } - return (!Platform.isWindows()) ? UnixDomainSocket.get(this.host) : NamedPipeSocket.get(this.host); - } - - @Override - public Socket connectSocket(TimeValue connectTimeout, Socket socket, HttpHost host, - InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context) - throws IOException { - return socket; - } - - } - /** * {@link HttpRoutePlanner} for local Docker. */ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/RemoteHttpClientTransport.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/RemoteHttpClientTransport.java index 0ab8d1ef6e..1b8d84260d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/RemoteHttpClientTransport.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/transport/RemoteHttpClientTransport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +25,8 @@ import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; -import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.http.ssl.TlsSocketStrategy; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.util.Timeout; @@ -74,7 +74,7 @@ final class RemoteHttpClientTransport extends HttpClientTransport { .create() .setDefaultSocketConfig(socketConfig); if (host.isSecure()) { - connectionManagerBuilder.setSSLSocketFactory(getSecureConnectionSocketFactory(host, sslContextFactory)); + connectionManagerBuilder.setTlsSocketStrategy(getTlsSocketStrategy(host, sslContextFactory)); } HttpClientBuilder builder = HttpClients.custom(); builder.setConnectionManager(connectionManagerBuilder.build()); @@ -83,13 +83,12 @@ final class RemoteHttpClientTransport extends HttpClientTransport { return new RemoteHttpClientTransport(builder.build(), httpHost); } - private static LayeredConnectionSocketFactory getSecureConnectionSocketFactory(DockerHost host, - SslContextFactory sslContextFactory) { + private static TlsSocketStrategy getTlsSocketStrategy(DockerHost host, SslContextFactory sslContextFactory) { String directory = host.getCertificatePath(); Assert.hasText(directory, () -> "Docker host TLS verification requires trust material location to be specified with certificate path"); SSLContext sslContext = sslContextFactory.forDirectory(directory); - return new SSLConnectionSocketFactory(sslContext); + return new DefaultClientTlsStrategy(sslContext); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java index 4fc33b705c..8a1efdcecd 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java @@ -36,8 +36,8 @@ import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.core5.http.io.SocketConfig; import org.eclipse.jetty.client.transport.HttpClientTransportDynamic; import org.eclipse.jetty.io.ClientConnector; @@ -209,9 +209,8 @@ public final class ClientHttpRequestFactories { } if (sslBundle != null) { SslOptions options = sslBundle.getOptions(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslBundle.createSslContext(), - options.getEnabledProtocols(), options.getCiphers(), new DefaultHostnameVerifier()); - connectionManagerBuilder.setSSLSocketFactory(socketFactory); + connectionManagerBuilder.setTlsSocketStrategy(new DefaultClientTlsStrategy(sslBundle.createSslContext(), + options.getEnabledProtocols(), options.getCiphers(), null, new DefaultHostnameVerifier())); } PoolingHttpClientConnectionManager connectionManager = connectionManagerBuilder.useSystemProperties() .build(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java index 1b684e9818..7595f052d6 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; @@ -64,7 +65,8 @@ import org.apache.coyote.http11.Http11Nio2Protocol; import org.apache.hc.client5.http.HttpHostConnectException; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.http.ssl.TlsSocketStrategy; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.NoHttpResponseException; import org.apache.hc.core5.ssl.SSLContextBuilder; @@ -670,12 +672,12 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory this.webServer = factory.getWebServer(); this.webServer.start(); RememberingHostnameVerifier verifier = new RememberingHostnameVerifier(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(), verifier); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(); + TlsSocketStrategy tlsSocketStrategy = new DefaultClientTlsStrategy(sslContext, verifier); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(tlsSocketStrategy); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); assertThat(verifier.getLastPrincipal()).isEqualTo("CN=1"); - requestFactory = createHttpComponentsRequestFactory(socketFactory); + requestFactory = createHttpComponentsRequestFactory(tlsSocketStrategy); bundles.updateBundle("test", createPemSslBundle("classpath:org/springframework/boot/web/embedded/tomcat/2.crt", "classpath:org/springframework/boot/web/embedded/tomcat/2.key")); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); @@ -690,9 +692,8 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks")); this.webServer = factory.getWebServer(); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index ca9270d209..1659290e10 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -29,7 +29,9 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -89,7 +91,8 @@ import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.http.ssl.TlsSocketStrategy; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.io.HttpClientResponseHandler; import org.apache.hc.core5.http.protocol.HttpContext; @@ -260,7 +263,7 @@ public abstract class AbstractServletWebServerFactoryTests { } @Test - void stopServlet() throws Exception { + void stopServlet() { AbstractServletWebServerFactory factory = getFactory(); this.webServer = factory.getWebServer(exampleServletRegistration()); this.webServer.start(); @@ -443,9 +446,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(ssl); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThatExceptionOfType(SSLException.class) .isThrownBy(() -> getResponse(getLocalUrl("https", "/hello"), requestFactory)); } @@ -456,9 +458,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThat(getResponse(getLocalUrl("https", "/hello"), requestFactory)).contains("scheme=https"); } @@ -474,7 +475,7 @@ public abstract class AbstractServletWebServerFactoryTests { TrustStrategy trustStrategy = new SerialNumberValidatingTrustSelfSignedStrategy("14ca9ba6abe2a70d"); SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, trustStrategy).build(); PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext)) + .setTlsSocketStrategy(new DefaultClientTlsStrategy(sslContext)) .build(); HttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build(); String response = getResponse(getLocalUrl("https", "/hello"), @@ -504,10 +505,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(socketFactory) + .setTlsSocketStrategy(createTrustSelfSignedTlsSocketStrategy()) .build(); HttpClient httpClient = this.httpClientBuilder.get().setConnectionManager(connectionManager).build(); ClientHttpResponse response = getClientResponse(getLocalUrl("https", "/hello"), HttpMethod.GET, @@ -522,10 +521,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks")); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(socketFactory) + .setTlsSocketStrategy(createTrustSelfSignedTlsSocketStrategy()) .build(); HttpClient httpClient = this.httpClientBuilder.get().setConnectionManager(connectionManager).build(); ClientHttpResponse response = getClientResponse(getLocalUrl("https", "/hello"), HttpMethod.GET, @@ -539,9 +536,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(null, "password", keyStore)); this.webServer = factory.getWebServer(); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -554,11 +550,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance("pkcs12"); loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "secret".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "secret".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -571,11 +567,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance("pkcs12"); loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "secret".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "secret".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -590,11 +586,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance("pkcs12"); loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "secret".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "secret".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -609,11 +605,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance("pkcs12"); loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "secret".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "secret".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -627,11 +623,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "password".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "password".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -642,9 +638,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(ClientAuth.NEED, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); String localUrl = getLocalUrl("https", "/test.txt"); assertThatIOException().isThrownBy(() -> getResponse(localUrl, requestFactory)); } @@ -659,11 +654,11 @@ public abstract class AbstractServletWebServerFactoryTests { this.webServer.start(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks")); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) - .loadKeyMaterial(keyStore, "password".toCharArray()) - .build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .loadKeyMaterial(keyStore, "password".toCharArray()) + .build(); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + new DefaultClientTlsStrategy(sslContext)); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -674,9 +669,8 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(ClientAuth.WANT, "password", "classpath:test.jks")); this.webServer = factory.getWebServer(); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory)).isEqualTo("test"); } @@ -772,16 +766,15 @@ public abstract class AbstractServletWebServerFactoryTests { factory.setSsl(getSsl(null, "password", "src/test/resources/restricted.jks", null, protocols, ciphers)); this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello")); this.webServer.start(); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( - new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build()); - HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory); + HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory( + createTrustSelfSignedTlsSocketStrategy()); assertThat(getResponse(getLocalUrl("https", "/hello"), requestFactory)).contains("scheme=https"); } protected HttpComponentsClientHttpRequestFactory createHttpComponentsRequestFactory( - SSLConnectionSocketFactory socketFactory) { + TlsSocketStrategy tlsSocketStrategy) { PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(socketFactory) + .setTlsSocketStrategy(tlsSocketStrategy) .build(); HttpClient httpClient = this.httpClientBuilder.get().setConnectionManager(connectionManager).build(); return new HttpComponentsClientHttpRequestFactory(httpClient); @@ -1635,6 +1628,12 @@ public abstract class AbstractServletWebServerFactoryTests { protected abstract String startedLogMessage(); + protected TlsSocketStrategy createTrustSelfSignedTlsSocketStrategy() + throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(); + return new DefaultClientTlsStrategy(sslContext); + } + private final class TestGzipInputStreamFactory implements InputStreamFactory { private final AtomicBoolean requested = new AtomicBoolean();