2014-09-15 30 views
8

Ich versuche herauszufinden, wie man eine erfolgreiche HTTP-GET-Anfrage an einen Server sendet, der SNI benötigt.Wie SNI in HTTP-Anfrage mit Apache HTTPComponents HttpClient aktivieren?

Ich suchte auf SO und anderen Orten und fand einige Artikel, die sagten, dass SNI jetzt in JDK7, sowie Apache HTTP-Komponenten unterstützt wird.

https://issues.apache.org/jira/browse/HTTPCLIENT-1119 https://wiki.apache.org/HttpComponents/SNISupport

Relevante SO Artikel: Certificate chain different between HTTPSURLconnection and Apache (System) DefaultHttpClient

-

Allerdings kann ich nicht scheinen, alle Dokumente zu finden, die zeigen, wie diese Arbeit zu bekommen. Hier

ist der Code, ich verwende ...


      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(); }

Wenn ich dies ausführen, schlägt die Anforderung fehl.

Der Server erfordert SNI in der Anforderung, und ohne sie gibt es ein abgelaufenes Cert zurück, das den falschen CommonName hat, aufgrund dessen es zurückgewiesen wird.

Wenn ich die Instanz httpclient2 verwende, die mit einem benutzerdefinierten SSL-Kontext eingerichtet wird, um alle HTTPS zuzulassen, ist die Anforderung erfolgreich. Dies möchte ich jedoch nicht auf einem Server aktivieren, der viele Downloads pro Tag gegen verschiedene Hosts durchführt.

Ich bin mit Httpclient v 4.3.5

Jede Hilfe sehr geschätzt.

Danke.

Antwort

7

SNI sollte vollständig transparent arbeiten, wenn es auf Java 1.7 oder neuer läuft. Keine Konfiguration ist erforderlich. Wenn aus irgendeinem Grund ein SSL-Handshake mit einem SNI-fähigen Server fehlschlägt, sollten Sie herausfinden, warum (und ob die SNI-Erweiterung ordnungsgemäß verwendet wurde), indem Sie die SSL-Debugprotokollierung wie hier [1] und hier [2]

aktivieren

"Debugging SSL/TLS Connections" kann veraltet aussehen, aber es kann immer noch nützlich sein, wenn Sie SSL-bezogene Probleme beheben.

[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

+0

ich den Code durch Maven ausgeführt wird. Obwohl java7 jre auf dem Weg war und es ermöglichte, nahm maven immer noch den alten jre auf. Ich weiß nicht warum. Als ich den Code in eine separate Klasse isoliert und über jre7 ausgeführt habe, hat es funktioniert. – feroze