Como habilitar o SNI na solicitação HTTP usando o Apache HTTPComponents HttpClient?
Estou tentando descobrir como enviar uma solicitação HTTP GET bem-sucedida para um servidor que requer SNI.
Pesquisei no SO e em outros lugares e encontrei alguns artigos que diziam que o SNI agora é suportado no JDK7, bem como no Apache HTTP Components.
https://issues.apache.org/jira/browse/HTTPCLIENT-1119 https://wiki.apache.org/HttpComponents/SNISupport
Artigo relevante do SO:Cadeia de certificados diferente entre HTTPSURLconnection e Apache (System) DefaultHttpClient
-
No entanto, não consigo encontrar nenhum documento que mostre como fazer isso funcionar.
Aqui está o código que estou usando ...
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();
}<p></p>
// 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();
}
Quando executo isso, a solicitação falha.
O servidor requer SNI na solicitação e, sem ela, retorna um certificado expirado com o CommonName errado, devido ao qual é rejeitado.
Se eu usar a instância httpclient2, que é configurada usando um contexto SSL personalizado para permitir todos os certificados hTTP, a solicitação será bem-sucedida. No entanto, isso não é algo que eu desejo habilitar em um servidor que faz muitos downloads por dia em hosts diferentes.
Estou usando o httpclient v 4.3.5
Qualquer ajuda apreciada.
Obrigado.