Created
October 16, 2017 23:47
-
-
Save beders/51d3600d7fb57ad7d36a1745749ef641 to your computer and use it in GitHub Desktop.
Glorious hack to use Java 9 HttpClient with servers enforcing SNI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package us.monoid.resty.hack; | |
import javax.net.ssl.*; | |
import java.security.*; | |
import java.util.List; | |
/** Glorious hack to always create an SSL Engine with a hostname and port. | |
* engineGetServerSessionContext and engineGetClientSessionContext can't be implemented without violating class/module loading constraints, | |
* but for some reason, they are not being called. | |
* */ | |
public class ForceHostnameVerificationSSLContext extends SSLContext { | |
String hostname; | |
public ForceHostnameVerificationSSLContext(String hostname, int port) { | |
super(new ForcedSSLContextSpi(hostname, port), null, "Default"); | |
this.hostname = hostname; | |
} | |
public SSLParameters getParametersForSNI() { | |
SSLParameters params = null; | |
try { | |
params = SSLContext.getDefault().getDefaultSSLParameters(); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
params.setServerNames(List.of(new SNIHostName(hostname))); | |
params.setEndpointIdentificationAlgorithm("HTTPS"); | |
return params; | |
} | |
public static class ForcedSSLContextSpi extends SSLContextSpi { | |
private final String hostname; | |
private final int port; | |
public ForcedSSLContextSpi(String hostname, int port) { | |
this.hostname = hostname; | |
this.port = port; | |
} | |
@Override | |
protected void engineInit(KeyManager[] keyManagers, TrustManager[] trustManagers, SecureRandom secureRandom) throws KeyManagementException { | |
} | |
@Override | |
protected SSLSocketFactory engineGetSocketFactory() { | |
try { | |
return SSLContext.getDefault().getSocketFactory(); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
@Override | |
protected SSLServerSocketFactory engineGetServerSocketFactory() { | |
try { | |
return SSLContext.getDefault().getServerSocketFactory(); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
@Override | |
protected SSLEngine engineCreateSSLEngine() { | |
try { | |
return SSLContext.getDefault().createSSLEngine(hostname, port); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
@Override | |
protected SSLEngine engineCreateSSLEngine(String host, int port) { | |
try { | |
return SSLContext.getDefault().createSSLEngine(host, port); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
@Override | |
protected SSLSessionContext engineGetServerSessionContext() { | |
return null; | |
} | |
@Override | |
protected SSLSessionContext engineGetClientSessionContext() { | |
return null; | |
} | |
} | |
} |
Why would you need this?
Turns out the new http client in jdk.incubator.http doesn't support SNI yet. That significantly reduces compatibility with many HTTPS servers. One example is https://jsonplaceholder.typicode.com/posts
which works just fine with the regular HTTP client.
The new http client will need significant improvement before inclusion into JDK 10.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use this with the new HttpClient like this: