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
Warum werden Zertifikate beantragt HttpsURLConnection
aber nicht für HttpClient
? Was mache ich falsch?
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. –