发出没有证书的HTTPS请求在桌面上不起作用

时间:2018-12-05 11:10:21

标签: java rest https postman

我必须访问Https API。它与 Postman Android Asynchronous Http Client库一起工作正常。

但是当我在桌面Java应用程序上尝试时,它只是说:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

javax.servlet.ServletException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:420)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

我无法使用的桌面代码:

HttpURLConnection con;
            String response;
            try {
                con = (HttpURLConnection) new URL(LOGIN_URL).openConnection();
                con.setDoOutput(true);
                con.setRequestMethod("GET");
                OutputStream os = con.getOutputStream(); //throws error
                os.flush();
                return "200";
            } catch (Exception e) {
                e.printStackTrace();
                return e.toString();
            }

我的Android工作代码:

AsyncHttpClient client = new AsyncHttpClient();
            RequestParams rp = new RequestParams();
            client.get("LOGIN_URL", rp, new AsyncHttpResponseHandler() {

                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] response) {

                    return new String(response); //works
                }

            });

所以,我的问题是:如果可以使其在Android上运行,为什么不能使用 Apache HttpComponents HttpURLConnection 方法?

有没有我可以使用的库,而无需安装任何证书,就像在Android上一样?出于服务器原因,我只想信任没有它的Web服务。

2 个答案:

答案 0 :(得分:1)

可能是因为Postman信任您明确表示已信任浏览的证书,但Java不信任。

尝试使用此solution to the SSLHandshakeException

  

当您的服务器具有自签名证书时,出现此问题。至   解决方法,您可以将此证书添加到受信任的列表中   JVM的证书。

     

this article中   作者介绍了如何从浏览器中获取证书,以及   将其添加到JVM的cacerts文件中。您可以编辑   JAVA_HOME / jre / lib / security / cacerts文件或使用以下命令运行应用程序   -Djavax.net.ssl.trustStore参数。验证您也正在使用哪个JDK / JRE,因为这经常会引起混乱。

     

另请参阅:How are SSL certificate server names resolved/Can I add alternative names using keytool?   如果遇到java.security.cert.CertificateException:无名称   匹配的本地主机发现异常。

答案 1 :(得分:1)

您需要将根链添加到CA证书文件中,以便Java可以验证自签名证书。

Postman信任您已在浏览器中明确信任的证书。

要更新您的CA certs文件,您需要找到它,因为您可能已安装了JDK,而您要查找的文件很可能位于JDK的JRE文件夹中。 ./jdk1.8/jre/lib/security/cacerts

要将Java添加到您的信任库中,请使用keytool(如果Java在您的环境路径上),首先运行以下命令,其中example.der是您的证书。我也建议您给它起一个更好的别名。

keytool -import -alias example -keystore /path/to/cacerts -file example.der

系统将提示您输入密码,java的默认值为changeit,输入密码,并在询问您是否信任证书时输入yes

添加证书后,您可以再次使用keytool列出您在密钥库中拥有的所有证书,再次提示您输入密码。

keytool -list -v -keystore /path/to/cacerts

当我运行此命令时,我会得到一个列表。您应该能够找到别名为example的证书。这是我列表中的第一名。

Alias name: digicertglobalrootca [jdk]
Creation date: 26 Aug. 2016
Entry type: trustedCertEntry

Owner: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
Issuer: CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
Serial number: 83be056904246b1a1756ac95991c74a
Valid from: Fri Nov 10 10:00:00 AEST 2006 until: Mon Nov 10 10:00:00 AEST 2031
Certificate fingerprints:
     SHA1: A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
     SHA256: 43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

您已更新问题,以包括要忽略证书的信息...

  

请不要忽略证书错误。相反,应对它们。   忽略证书错误将打开与潜在MITM的连接   攻击。诱人的是,它仅用于测试代码,不会在   生产,但我们都知道截止日期临近时会发生什么:   该代码在测试时没有显示任何错误->我们可以发货   照原样。

现在,我知道您决心要执行此操作-here是一些相关代码。

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}

// Now you can access an https URL without having the certificate in the truststore
try {
    URL url = new URL("https://hostname/index.html");
} catch (MalformedURLException e) {
}