2016-04-19 7 views
1

Ich habe eine Webanwendung (auf WebSphere), die mit Drittanbieter interagiert, um einige empfangene Daten zu formatieren, und dann RESTful Anruf an besagten Drittanbieter, der sich auf einem Tomcat server befindet. Innerhalb der Web-App kann ich erfolgreich einen grundlegenden RESTful GET Aufruf mit Java nativen HttpsUrlConnection (siehe unten), aber wenn ich Apache HttpClient verwenden, schlägt es mit einem SSL Verkettung Fehler.Mit https URL funktioniert HttpsURLConnection, aber HttpClient nicht

Die HttpsURLConnection:

String urlWithParams = "https://example.com/rest/issue/59"; 

    String methodType = "GET"; 
    String acceptType = MediaType.APPLICATION_JSON; 

    HttpsURLConnection conn = null; 

    try { 

     URL url = new URL(urlWithParams); 
     conn = (HttpsURLConnection) url.openConnection(); 
     conn.setRequestMethod(methodType); 
     conn.setRequestProperty("Accept", acceptType); 

     if (conn.getResponseCode() != 200) { 
      System.out.println("Failed. httpErrorUrl=" + conn.getResponseCode() 
        + " httpErrorCode=" + conn.getResponseCode() 
        + " httpErrorMsg=" + conn.getResponseMessage()); 

     } 

     BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 

     String rawData; 
     String toReturn = ""; 
     while ((rawData = br.readLine()) != null) { 
      toReturn += rawData; 
     } 

     System.out.println(toReturn); 

    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally{ 
     if(conn != null){ 
      conn.disconnect(); 
     } else { 
      System.out.println("httpUrlConnection is null"); 
     } 
    } 

Der Httpclient-Code:

String uri = "https://example.com/rest/issue/59"; 
    PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); 
    connManager.setDefaultMaxPerRoute(20); 
    connManager.setMaxTotal(40); 

    CloseableHttpClient httpclient = HttpClients.createDefault(); 

Die Httpclient Methode in der Funktion unten ausgeführt:

private JSON request(HttpRequestBase req) throws RestException, IOException { 
     req.addHeader("Accept", "application/json"); 

     if (creds != null) 
      creds.authenticate(req); 

     HttpResponse resp = httpClient.execute(req); 
     HttpEntity ent = resp.getEntity(); 
     StringBuilder result = new StringBuilder(); 

     if (ent != null) { 
      String encoding = null; 
      if (ent.getContentEncoding() != null) { 
       encoding = ent.getContentEncoding().getValue(); 
      } 

      if (encoding == null) { 
       Header contentTypeHeader = resp.getFirstHeader("Content-Type"); 
       HeaderElement[] contentTypeElements = contentTypeHeader.getElements(); 
       for (HeaderElement he : contentTypeElements) { 
        NameValuePair nvp = he.getParameterByName("charset"); 
        if (nvp != null) { 
         encoding = nvp.getValue(); 
        } 
       } 
      } 

      InputStreamReader isr = encoding != null ? 
       new InputStreamReader(ent.getContent(), encoding) : 
       new InputStreamReader(ent.getContent()); 
      BufferedReader br = new BufferedReader(isr); 
      String line = ""; 

      while ((line = br.readLine()) != null) 
       result.append(line); 
     } 

     StatusLine sl = resp.getStatusLine(); 

     if (sl.getStatusCode() >= 300) 
      throw new RestException(sl.getReasonPhrase(), sl.getStatusCode(), result.toString()); 

     return result.length() > 0 ? JSONSerializer.toJSON(result.toString()): null; 
    }  

Der erzeugte Fehler ist eine typische Verkettungs Ausnahme , was normalerweise bedeutet, dass die SSL Zertifikate nicht korrekt sind. Da die Zertifikate auf der App-Server-Ebene importiert werden, würde ich erwarten, dass die SSL-Verbindungen sowohl für die Anrufe HttpsURLConnection als auch für die HttpClient-Verbindung gleich behandelt werden.

Caused by: `com.ibm.jsse2.util.j: PKIX` path building failed: `java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl` co 

ULD keine gültige CertPath.; interne Ursache bauen ist: java.security.cert.CertPathValidatorException: Das Zertifikat von CN = Entrust Root Certification Authority, OU = "(c) 2 006 Entrust, Inc.", OU = www.entrust .net/CPS wird durch Verweis einbezogen, O = "Entrust, Inc.", C = US ist nicht vertrauenswürdig; innere Ursache ist:

`java.security.cert.CertPathValidatorException:` Certificate chaining error 
    at com.ibm.jsse2.util.h.b(h.java:18) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.util.h.b(h.java:118) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.util.g.a(g.java:14) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.pc.a(pc.java:41) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.pc.checkServerTrusted(pc.java:1) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.pc.b(pc.java:90) ~[na:6.0 build_20141024] 
    at com.ibm.jsse2.lb.a(lb.java:499) ~[na:6.0 build_20141024] 
    ... 80 common frames omitted 

Verursacht durch: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl keine gültige CertPath bauen könnte. [Na: na] bei com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:411) ~ bei java.security.cert.CertPathBuilder.build(CertPathBuilder.java:258) ~ [na: na] bei com.ibm.jsse2.util.h.b(h.java:61) ~[na:6.0 build_20141024] ... 86 gemeinsamen Rahmen

weggelassen

Warum werden Zertifikate beantragt HttpsURLConnection aber nicht für HttpClient? Was mache ich falsch?

+0

Meine Vermutung, das ist ein Problem mit SNI, siehe http: // stackoverflow.com/fragen/5879894/android-ssl-sni-support. Wenn dieser Post Form 2011 ist, ist es immer noch relevant. –

Antwort

2

HttpClient berücksichtigt Systemeigenschaften nur, wenn explizit dafür konfiguriert wurde.

Try

HttpClients.createDefault() 

mit

HttpClients.createSystem() 

ersetzen Bitte beachten Sie auch, dass PoolingHttpClientConnectionManager Instanz in Ihrem Code nicht verwendet wird. Erstellen Sie keine benutzerdefinierten Verbindungs-Manager, es sei denn, Sie haben einen guten Grund, dies zu tun.

+0

Danke @oleg.Wow, ich kann nicht glauben, nach all meiner Google-Suche auf Apache HttpClient und SSL Ich bin nicht auf HttpClients.createSystem() gestoßen. Vielen Dank für die Info, es behoben meine Probleme –

+0

Das hat auch in unserem Fall gut funktioniert. –

0

Die folgende Frage enthält ein gutes Codebeispiel zur Verwendung von HTTPS über HttpClient.

Using Apache httpclient for https

Kurz gesagt: Ihr Code alle HTTP S spezifischen Setup fehlt .. Sie verwenden es, als ob es nur eine ganz normale HTTP-Anforderung war.

+0

Ich bin mir nicht sicher, ob ich verstehe, was du sagst. In der [HttpClient SSL Docs] (http://hc.apache.org/httpclient-3.x/sslguide.html) heißt es: ** Sobald Sie JSSE korrekt installiert haben, sollte die sichere HTTP-Kommunikation über SSL so einfach sein als einfache HTTP-Kommunikation **. Da die Quelle meines Aufrufs innerhalb von WebSphere liegt, sollte sie alle SSL-Verhandlungen abwickeln (wie wenn ich HttpsURLConnection verwende, richtig?) –

+0

Scheint nicht so, als ob es jetzt der Fall ist. Versuchen Sie das Beispiel, das im verlinkten Post gegeben wird und sehen, ob es funktioniert .. – MichaelK

Verwandte Themen