2016-04-19 20 views
1

受信したデータをフォーマットするために第三者とやりとりするWebアプリケーション(WebSphere上)があり、Tomcat serverにある第三者にRESTful呼び出しを行います。 Webアプリケーション内では、JavaのネイティブHttpsUrlConnection(下記参照)を使用して、基本的なRESTful GET呼び出しを正常に作成できますが、ApacheのHttpClientを使用するとSSLチェーンエラーが発生します。https URLでHttpsURLConnectionは動作しますが、HttpClientは動作しません。

の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"); 
     } 
    } 

HttpClientをコード:

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

    CloseableHttpClient httpclient = HttpClients.createDefault(); 

のHttpClientの方法は、以下の関数で実行される:

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

生成誤差は、典型的な連鎖例外でありますこれは通常、SSLの証明書が正しくないことを意味します。証明書はApp Serverレベルでインポートされるため、SSL接続はHttpsURLConnectionHttpClientの両方の呼び出しで同じように扱われると思います。

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

有効CertPath.;内部原因を構築しませULDです: java.security.cert.CertPathValidatorException: CN =のEntrustルート証明機関によって発行された証明書、OU = "(C)2 006エントラスト社"、OU = www.entrust .net/CPSは参照により組み込まれ、O = "Entrust、Inc."、C = USは信頼されていません。内部の原因は次のとおりです。java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImplは、有効な証明書パスを構築することができませんでした:によって引き起こさ

`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 

com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:411)〜[ナ:ナ]で java.security.cert.CertPathBuilder.build(CertPathBuilder.java:258)〜で [NA:ナ] com.ibm.jsse2.util.h.b(h.java:61) ~[na:6.0 build_20141024] ... 86共通フレームで はなぜ証明書がHttpsURLConnectionのためではなく、HttpClientのために適用されている

を省略しましたか?私は間違って何をしていますか?

+0

これはSNIの問題です。http:// stackoverflowを参照してください。com/questions/5879894/android-ssl-sni-supportもしこの投稿が2011年の形であれば、まだ関連性があります。 –

答えて

2

明示的に構成されていない限り、HttpClientはシステムプロパティを考慮しません。

HttpClients.createSystem() 

HttpClients.createDefault() 

を交換してください試してみてくださいまた、あなたのコード内のPoolingHttpClientConnectionManagerインスタンスが使用されていないことに注意してください。カスタム接続マネージャを作成しないでください。そうしなければならない理由があります。

+0

おかげさまで、Apache HttpClientとSSLで検索した私のすべてのGoogleがHttpClients.createSystem()を見つけたのは信じられませんでした。情報をありがとうございました。問題を修正しました –

+0

これは我々のケースでもうまくいきました。 –

0

次の質問は、HTTPSをHttpClientで使用する方法の良いコード例です。簡単に言うと

Using Apache httpclient for https

:あなたのコードは、HTTP S特定のセットアップのすべてが欠落しているそれだけで通常のHTTPリクエストであるかのように..あなたはそれを使用しています。

+0

私はあなたが何を言っているのか分かりません。 [HttpClient SSL Docs](http://hc.apache.org/httpclient-3.x/sslguide.html)には、** JSSEが正しくインストールされていれば、SSLを介したセキュアなHTTP通信は単純なものでなければならない単純なHTTP通信**として。私の呼び出しのソースはWebSphere内にあるので、SSL交渉のすべてを処理する必要があります(HttpsURLConnectionを使用するときと同じように、右ですか? –

+0

リンクされたポストで与えられた例を試してみてください – MichaelK