【问题标题】:SunCertPathBuilderException: unable to find valid certification path to requested target in CN1 appSunCertPathBuilderException:无法在 CN1 应用程序中找到请求目标的有效证书路径
【发布时间】:2018-05-23 23:07:02
【问题描述】:

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

当我在 Postman 中运行请求时,它工作正常:

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)

为什么应用程序与发出呼叫的 Postman 有任何不同(网络监视器窗口确认相同的 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() 为空。

非常感谢

【问题讨论】:

  • 您似乎已经通过导入证书解决了这个问题。我遇到了类似的问题,并通过将 Java 8 的版本从 1.8.0_25-b17 升级到 1.8.0_241-b07 来修复它。你碰巧知道你运行的是什么版本吗?

标签: rest tomcat ssl https codenameone


【解决方案1】:

如果底层 JDK 无法识别签名权限,就会发生这种情况。假设您从有效来源购买证书,它可能使用相对较新的根,这意味着您需要使用最新版本的 JDK 8。

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

【讨论】:

  • 刚刚检查了 Tomcat 及其正在运行的 JDK 1.8 更新 171,这似乎足够高了。
  • 确认我的 cacerts 确实包含我的根 CA,所以不是这样。使用magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
  • 进一步阅读表明它可以很好地显示在我的证书层次结构中的中间证书。稍后我会将其添加到密钥库中。顺便说一句,我的密钥库不包含我的孩子证书(我买的那个)所以不知道这是否有问题?这里有很好的信息:stackoverflow.com/questions/6908948/…
  • 不幸的是我仍然有同样的问题。任何人都可以帮忙。我已成功将根证书、中介和我自己的证书添加到密钥库中。我可以看到他们在那里。反弹了所有东西,当我运行模拟器时它仍然出错。我已经阅读了很多论坛并处于空白状态。有需要检查的区域吗?谢谢
  • 模拟器中客户端JVM使用的JDK是否相同?这可能是在安装较旧的 JDK 吗?
【解决方案2】:

它现在正在工作。

  1. (在云 tomcat 上)我确保根证书和中间证书在我的密钥库中(根据我之前包含的链接)。我将我的 .ca-bundle 包含在了密钥库中。

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

  3. 它在我的模拟器上仍然出错,但在我的 iphone 上工作,这指向(如 Shai 所说)我期望的不同 JDK,因此将我的笔记本电脑升级到更高的 JDK 1.8.171。这本身并没有什么不同,但可能是必需的。

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

    cd %java_home%\jre\lib\security

    路径=%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 -import -alias purchase_cert -keystore cacerts -file C:\path\my_purchased_cert.crt

【讨论】:

    猜你喜欢
    • 2017-12-27
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    • 2020-11-25
    • 2020-11-24
    • 2021-04-14
    • 2020-11-11
    相关资源
    最近更新 更多