我无法使用HttpClient从SNI站点获取资源。我要提取的网址是:https://dabar.srce.hr/,https://www.lutrija.hr/cms/splash。
我收到此错误: javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure
据我了解文档,它应该像开箱即用(并且适用于非sni https站点):
url = "https://dabar.srce.hr/";
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
// trust all certificates
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslSF).build();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println(response.getStatusLine().toString());
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity));
我试图明确启用SNIExtension:
System.setProperty("jsse.enableSNIExtension", "true");
我尝试重写SSLConnectionSocketFactory:
SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE) {
String targetHost = "";
@Override
public Socket createLayeredSocket(Socket socket, String target, int port, HttpContext context)
throws IOException {
this.targetHost = target;
return super.createLayeredSocket(socket, target, port, context);
}
@Override
protected void prepareSocket(SSLSocket socket) throws IOException {
try {
PropertyUtils.setProperty(socket, "host", this.targetHost);
} catch (Exception ex) {
}
super.prepareSocket(socket);
}
@Override
public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context)
throws IOException {
if (socket instanceof SSLSocket) {
try {
PropertyUtils.setProperty(socket, "host", host.getHostName());
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
return super.connectSocket(connectTimeout, socket, host, remoteAddress,
localAddress, context);
}
};
我错过了什么?
答案 0 :(得分:2)
我遇到了同样的问题。这个自定义SSLConnectionSocketFactory为我修复了它:
public class TrustAllSslSocketFactory extends SSLConnectionSocketFactory { static final HostnameVerifier ALL_HOSTNAME_VERIFIER = (String hostname, SSLSession session) -> true; public TrustAllSslSocketFactory(SSLContext sslContext) { super(sslContext, ALL_HOSTNAME_VERIFIER); } @Override protected void prepareSocket(SSLSocket socket) throws IOException { String hostName = socket.getInetAddress().getHostName(); SNIHostName sniHostName = new SNIHostName(hostName); List serverNames = new ArrayList(1); serverNames.add(sniHostName); SSLParameters sslParameters = socket.getSSLParameters(); sslParameters.setServerNames(serverNames); socket.setSSLParameters(sslParameters); } }
请参阅http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SNIExamples