java - 对于 https URL,HttpsURLConnection 可以工作,但 HttpClient 不能

标签 java ssl apache-httpclient-4.x httpsurlconnection

我有一个 Web 应用程序(在 WebSphere 上),它与第 3 方交互以格式化一些接收到的数据,然后对位于 Tomcat server 上的所述第 3 方进行 RESTful 调用。 。在网络应用程序中,我可以成功制作基本的 RESTful GET使用Java原生调用HttpsUrlConnection (见下文),但是当我使用 Apache 的 HttpClient 时,失败并显示 SSL链接错误。

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证书不正确。由于证书是在应用程序服务器级别导入的,因此我预计 SSL HttpsURLConnection 的连接处理方式相同和HttpClient来电。

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

无法构建有效的CertPath.;内因是: java.security.cert.CertPathValidatorException: CN=Entrust Root Certification Authority 颁发的证书,OU="(c) 2 006 Entrust, Inc.", OU=www.entrust.net/CPS 通过引用并入,O="Entrust, Inc.", C=US 不受信任;内部原因是:

    `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

原因:java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl 无法构建有效的 CertPath。 在com.ibm.security.cert.PKIXCertPathBuilderImpl.engineBuild(PKIXCertPathBuilderImpl.java:411) 〜[娜:娜] 在java.security.cert.CertPathBuilder.build(CertPathBuilder.java:258) 〜[娜:娜] 在com.ibm.jsse2.util.h.b(h.java:61) ~[na:6.0 build_20141024] ... 86常用框架省略

为什么要申请证书HttpsURLConnection但不适用于HttpClient ?我究竟做错了什么?

最佳答案

除非明确配置为 do do,否则 HttpClient 不会考虑系统属性。

尝试更换

HttpClients.createDefault()

HttpClients.createSystem()

另请注意,您的代码中未使用 PoolingHttpClientConnectionManager 实例。除非有充分的理由,否则不要创建自定义连接管理器。

关于java - 对于 https URL,HttpsURLConnection 可以工作,但 HttpClient 不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36721468/

相关文章:

java - 如何在 HBase 过滤器中混合使用 MUST_PASS_ALL 和 MUST_PASS_ONE?

java - Android 4:通过隧道将整个设备传输到代理

java - 无法将 ArrayList 数据加载到 android 中的微调器

java - 函数参数优化的最终结果

java - 证书链中的 SSLHandshakeException 行为

ssl - Netty ClientBootstrap SSL 握手终止——Channel/ClientBootstrap 关闭?

java - Android HttpClient 使用 java.lang.OutOfMemoryError : pthread_create 使应用程序崩溃

java - One Note Api 拒绝承载 token ,错误 401

ssl - 更改证书 csr 的指纹 SHA

Android Http 请求 - 如何禁用缓存