代码之家  ›  专栏  ›  技术社区  ›  Think.Smart

SUNCertPathBuilderException:无法在CN1应用程序中找到请求目标的有效证书路径

  •  1
  • Think.Smart  · 技术社区  · 6 年前

    请你帮忙。 我有一个codenameone应用程序,它向一个云Tomcat8服务器发出一个get请求,并期望返回一些响应JSON。重要的是,这是一个HTTPS调用。

    当我以邮递方式运行请求时,它工作正常:

    https://www.mydomain.co.uk:8443/MyProject/v1/generate_token

    通过浏览器的同一个URL工作并显示为“安全”,我可以看到我的证书详细信息。 我已经为我的ssl/tls配置购买了一个证书,并且在启动时在日志中似乎可以正常工作。

    在模拟器中,我在从URL调用中读取响应时返回以下错误-我想必须对其进行加密:

    Exception: 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.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
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1564)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:347)
        at com.codename1.impl.javase.JavaSEPort.getResponseCode(JavaSEPort.java:7591)
        at com.codename1.io.ConnectionRequest.performOperation(ConnectionRequest.java:702)
        at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:282)
        at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
    

    为什么应用程序与进行呼叫的邮递员有任何不同(网络监视器窗口确认相同的URL呼叫)?

    我打电话后没有更新任何日志,因此没有要检查的内容。自从从HTTP迁移到HTTPS之后,我没有对我的应用程序做任何更改(它正在工作)。

    以下是拨打电话的CN1代码:

    public String fetchTokenIntoStorage(String userName, String password) {
            ConnectionRequest r = new ConnectionRequest();
            r.setUrl(Constants.URL_HOST_PORT + "/MyProject" + Constants.LIVE_OR_TEST
                    + "/v1/generate_token");
            r.addRequestHeader("Content-Type", "application/json");
            r.addRequestHeader("userName", userName);
            r.addRequestHeader("password", password);
            r.setHttpMethod("GET");
            r.setFailSilently(false);
            r.setPost(false);
            // show spinning dialog while connecting
            InfiniteProgress prog = new InfiniteProgress();
            Dialog dlg = prog.showInifiniteBlocking();
            r.setDisposeOnCompletion(dlg);
            NetworkManager.getInstance().setTimeout(10000);
            // NetworkManager.getInstance().addErrorListener(new ActionListener() {
            //
            // @Override
            // public void actionPerformed(ActionEvent evt) {
            // MessageBox.showDialogMessage("Unable to connect to server. Please
            // retry later.");
            // }
            // });
            // NetworkManager.getInstance().updateThreadCount(2);
            NetworkManager.getInstance().addToQueueAndWait(r);
    
            if (r.getResponseData() != null) {
                JSONParser parser = new JSONParser();
                Map<String, Object> json = null;
                try {
                    json = parser.parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData())));
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (json.get("error") != null) {
                    return String.valueOf(json.get("error"));
                }
                JwtRecord record = new JwtRecord();
                record.userId = Integer.parseInt(String.valueOf(json.get("userId")));
                record.jsonWebToken = (String) json.get("jwt");
                record.theme = "LIGHT";
                Storage.getInstance().writeObject("MyToken", record);
                return "";
            }
            if (!r.getResponseErrorMessage().equalsIgnoreCase("")) {
                return r.getResponseErrorMessage();
            } else {
                return "Unable to connect to server. Please check connection.";
            }
        }
    

    单步执行代码后似乎出错

    NetworkManager.getInstance().addToQueueAndWait(r);
    

    r.GetResponsedata()和r.GetResponseErrorMessage()为空。

    非常感谢

    2 回复  |  直到 6 年前
        1
  •  3
  •   Shai Almog    6 年前

    如果基础JDK不识别签名权限,就会发生这种情况。假设您从一个有效的源购买了证书,它可能使用了一个相对较新的根,这意味着您需要使用最新版本的JDK8。

    例如。 letsencrypt 仅在JDK 8更新101中添加。

        2
  •  3
  •   Think.Smart    6 年前

    现在开始工作了。

    1. (在cloud tomcat上)我确保根证书和中间证书在我的密钥库中(根据我以前包含的链接)。我把我的.ca包放在密钥库中,以备不时之需。

    2. (在cloud tomcat上)我注意到我使用的是旧版本的Apache配置(关于依赖旧的论坛帖子的经验教训)。需要让sslcacertificatefile指向我的.ca包文件,而不是在apache.conf文件中使用sscertificatechainfile。

    3. 它在我的模拟器上仍然是错误的,但是在我的iPhone上工作,它指出(如Shai所说)不同于我所期望的JDK,所以把我的笔记本升级到更高的JDK 1.8.171。这本身没有什么不同,但可能是必要的。

    4. 通过四处挖掘,我意识到笔记本电脑上的模拟器也需要上述功能。所以我以管理员的身份在命令提示符下运行了下面的语句,现在我的模拟器正在工作。

      cd%java_home%\jre\lib\安全

      路径=%java_home\bin

      keytool-import-alias comodo-keystore cacerts-file c:\path\comodoroot.cer

      keytool-import-alias comodo_intermediate-keystore cacerts-file c:\path\comodointer.cer

      keytool-导入-别名已购买\u cert-keystore cacerts-文件C:\path\my\u已购买\u cert.crt