我想弄清楚如何向需要 SNI 的服务器发送成功的 HTTP GET 请求。
我在SO等地方搜索了一下,发现一些文章说JDK7现在支持SNI,还有Apache HTTP Components。
https://issues.apache.org/jira/browse/HTTPCLIENT-1119
https://wiki.apache.org/HttpComponents/SNISupport
相关SO文章:Certificate chain different between HTTPSURLconnection and Apache (System) DefaultHttpClient
——
但是,我似乎找不到任何说明如何使其工作的文档。
这是我正在使用的代码...
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
String trustedCertsPath = System.getenv("JAVA_HOME") + "/jre/lib/security/cacerts";
FileInputStream certstream = new FileInputStream(new File(trustedCertsPath));
try {
trustStore.load(certstream, "changeit".toCharArray());
} finally {
certstream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient2 = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(uri);
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
tempFile = File.createTempFile(httpFile.getTempFilePrefix(), httpFile.getTempFilePosfix());
FileOutputStream os = new FileOutputStream(tempFile);
InputStream instream = entity.getContent();
try {
IOUtils.copy(instream, os);
} finally {
try { instream.close(); } catch (Exception e) {}
try { os.close(); } catch (Exception e) {}
}
}
} finally {
response.close();
}
当我运行它时,请求失败。
服务器在请求中需要 SNI,如果没有它,它会返回一个具有错误 CommonName 的过期证书,因此它被拒绝。
如果我使用 httpclient2 实例,即使用自定义 SSL 上下文设置以允许所有 hTTP 证书,则请求成功。但是,这不是我想在每天针对不同主机进行大量下载的服务器上启用的功能。
我正在使用 httpclient v 4.3.5
任何帮助表示赞赏。
谢谢。
最佳答案
SNI 在 Java 1.7 或更高版本上运行时应该完全透明地工作。无需配置。如果出于某种原因与启用 SNI 的服务器的 SSL 握手失败,您应该能够通过打开 SSL 调试日志记录来找出原因(以及是否正确使用了 SNI 扩展),如此处 [1] 和此处 [2] 所述
“调试 SSL/TLS 连接”可能看起来已经过时,但在解决 SSL 相关问题时它仍然很有用。
[1] http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/ReadDebug.html
[2] http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Debug
关于apache-httpclient-4.x - 如何使用 Apache HTTPComponents HttpClient 在 HTTP 请求中启用 SNI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25854543/