J'ai une application Web (sur WebSphere) qui interagit avec un tiers pour formater certaines données reçues, puis effectue un appel RESTful à ce tiers, qui réside sur un Tomcat server
. Dans l'application Web, je peux effectuer avec succès un appel RESTful GET
RESTful en utilisant HttpsUrlConnection
natif de Java (voir ci-dessous), mais lorsque j'utilise le HttpClient
d'Apache, il échoue avec une erreur de chaînage SSL
.Avec https URL, HttpsURLConnection fonctionne mais HttpClient ne fonctionne pas
Le 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");
}
}
Le code HttpClient:
String uri = "https://example.com/rest/issue/59";
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setDefaultMaxPerRoute(20);
connManager.setMaxTotal(40);
CloseableHttpClient httpclient = HttpClients.createDefault();
Les méthodes HttpClient sont exécutées dans la fonction ci-dessous:
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;
}
L'erreur produite est une exception de chaînage typique , ce qui signifie généralement que les certificats SSL
ne sont pas corrects. Puisque les certificats sont importés au niveau du serveur d'applications, je m'attendrais à ce que les connexions SSL
soient traitées de la même manière pour les appels HttpsURLConnection
et HttpClient
.
Caused by: `com.ibm.jsse2.util.j: PKIX` path building failed: `java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl` co
ULD ne pas construire une cause interne CertPath.;
valide est: java.security.cert.CertPathValidatorException:
Le certificat délivré par le CN = Entrust autorité de certification racine, OU = "(c) 2 006 Entrust, Inc.", OU = www.entrust .net/CPS est incorporé par référence, O = "Entrust, Inc.", C = US n'est pas fiable; cause interne est:
`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
causés par: java.security.cert.CertPathBuilderException:
PKIXCertPathBuilderImpl ne pouvait pas construire une CertPath valide. à com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:411)
~ [na: na] à java.security.cert.CertPathBuilder.build(CertPathBuilder.java:258)
~ [na: na] à com.ibm.jsse2.util.h.b(h.java:61) ~[na:6.0 build_20141024] ... 86
cadres communs omis
HttpsURLConnection
mais pas pour
HttpClient
? Qu'est-ce que je fais mal?
Je suppose que c'est un problème avec SNI, voir http: // stackoverflow.com/questions/5879894/android-ssl-sni-support. Si ce poste est de forme 2011, il est toujours pertinent. –