Details
-
Bug
-
Status: Resolved
-
Blocker
-
Resolution: Invalid
-
None
-
None
-
None
-
JDK 1.8, org.apache.httpcomponents.client5 5.0-beta1
Description
Hi
Getting following error when I configure CloseableHttpAsyncClient to use HTTP2 over SSL.
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:197)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at org.apache.hc.core5.reactor.ssl.SSLIOSession.receiveEncryptedData(SSLIOSession.java:443)
at org.apache.hc.core5.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:498)
at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:112)
at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:50)
at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:173)
at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:123)
at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:80)
at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
at java.lang.Thread.run(Thread.java:745)
Could you help, please? The complete code is provided in code section. Thanks.
Regards
Rajan
// App.java public static void main( String[] args ) throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); String trustStorePath = "C:\\cert\\keystore.jks"; String trustStorePassword = "password"; // SSLProvider should be used for all SSL related config like building a SSL context SSLProvider provider = new SSLProvider(); SSLContext sslContext = provider.buildSSLContext(null, null, trustStorePath, trustStorePassword); final TlsStrategy tlsStrategy = new H2TlsStrategy( sslContext, H2TlsStrategy.getDefaultHostnameVerifier()) { }; final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create() .setTlsStrategy(tlsStrategy) .build(); CloseableHttpAsyncClient client = HttpAsyncClients.custom().setConnectionManager(cm).setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2).build(); client.start(); final HttpHost target = new HttpHost("localhost", 1090, "https"); final String requestUri = "/rest/rest/helloWorld"; final HttpClientContext clientContext = HttpClientContext.create(); final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri); final Future<SimpleHttpResponse> future = client.execute( SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() { public void completed(final SimpleHttpResponse response) { System.out.println(requestUri + "->" + response.getCode()); System.out.println(response.getBody()); final SSLSession sslSession = clientContext.getSSLSession(); if (sslSession != null) { System.out.println("SSL protocol " + sslSession.getProtocol()); System.out.println("SSL cipher suite " + sslSession.getCipherSuite()); } countDownLatch.countDown(); } public void failed(final Exception ex) { ex.printStackTrace(); System.out.println(requestUri + "->" + ex); } public void cancelled() { System.out.println(requestUri + " cancelled"); } }); countDownLatch.await(); System.out.println("Shutting down"); client.shutdown(ShutdownType.GRACEFUL); } //SSLProvider.java public class SSLProvider { public SSLContext buildSSLContext(String keyStorePath, String keyStorePassword, String trustStorePath, String trustStorePassword) throws Exception { TrustManager trustManagers[] = null; KeyManager keyManagers[] = null; if(null != trustStorePath && !"".equalsIgnoreCase(trustStorePath)) { trustManagers = new TrustManager[] {new MyX509TrustManager(trustStorePath, trustStorePassword.toCharArray())}; } if(null != keyStorePath && !"".equalsIgnoreCase(keyStorePath)) { keyManagers = new KeyManager[] {new MyX509KeyManager(keyStorePath, keyStorePassword.toCharArray())}; } SSLContext context = SSLContext.getInstance("TLS"); context.init(keyManagers, trustManagers, null); return context; } static class MyX509TrustManager implements X509TrustManager { /* * The default PKIX X509TrustManager9. We'll delegate decisions to it, and fall back to the logic in this class if the default * X509TrustManager doesn't trust it. */ X509TrustManager pkixTrustManager; MyX509TrustManager(String trustStore, char[] password) throws Exception { this(new File(trustStore), password); } MyX509TrustManager(File trustStore, char[] password) throws Exception { // create a "default" JSSE X509TrustManager. KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(trustStore), password); TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(ks); TrustManager tms[] = tmf.getTrustManagers(); /* * Iterate over the returned trustmanagers, look for an instance of X509TrustManager. If found, use that as our "default" trust * manager. */ for(int i = 0; i < tms.length; i++) { if(tms[i] instanceof X509TrustManager) { pkixTrustManager = (X509TrustManager) tms[i]; return; } } /* * Find some other way to initialize, or else we have to fail the constructor. */ throw new Exception("Couldn't initialize"); } /* * Delegate to the default trust manager. */ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { pkixTrustManager.checkClientTrusted(chain, authType); } /* * Delegate to the default trust manager. */ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { pkixTrustManager.checkServerTrusted(chain, authType); } /* * Merely pass this through. */ public X509Certificate[] getAcceptedIssuers() { return pkixTrustManager.getAcceptedIssuers(); } } /** * Inspired from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html * */ static class MyX509KeyManager implements X509KeyManager { /* * The default PKIX X509KeyManager. We'll delegate decisions to it, and fall back to the logic in this class if the default * X509KeyManager doesn't trust it. */ X509KeyManager pkixKeyManager; MyX509KeyManager(String keyStore, char[] password) throws Exception { this(new File(keyStore), password); } MyX509KeyManager(File keyStore, char[] password) throws Exception { // create a "default" JSSE X509KeyManager. KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(keyStore), password); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE"); kmf.init(ks, password); KeyManager kms[] = kmf.getKeyManagers(); /* * Iterate over the returned keymanagers, look for an instance of X509KeyManager. If found, use that as our "default" key * manager. */ for(int i = 0; i < kms.length; i++) { if(kms[i] instanceof X509KeyManager) { pkixKeyManager = (X509KeyManager) kms[i]; return; } } /* * Find some other way to initialize, or else we have to fail the constructor. */ throw new Exception("Couldn't initialize"); } public PrivateKey getPrivateKey(String arg0) { return pkixKeyManager.getPrivateKey(arg0); } public X509Certificate[] getCertificateChain(String arg0) { return pkixKeyManager.getCertificateChain(arg0); } public String[] getClientAliases(String arg0, Principal[] arg1) { return pkixKeyManager.getClientAliases(arg0, arg1); } public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) { return pkixKeyManager.chooseClientAlias(arg0, arg1, arg2); } public String[] getServerAliases(String arg0, Principal[] arg1) { return pkixKeyManager.getServerAliases(arg0, arg1); } public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) { return pkixKeyManager.chooseServerAlias(arg0, arg1, arg2); } } public HostnameVerifier getHostNameVerfier() { return new HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { // a host can be termed as blocked or non-verified through some logic here;by returning false return true; } }; } }