javafx 16 WebEngine 异常“SSL 握手失败”

问题描述

我正在将一个 android 应用程序移植到 javaFX 以进行 Windows 部署,我是 javaFX 和桌面部署的新手,但对 java 并不陌生。

该应用程序包含一个 WebView,它加载通过 Json 从服务器获取的 url(因此基本上可以是任何东西)。

openJDK 14,openJfx 16,intellij idea Ultimate 2021.1.3,gradle: plugins: org.beryx.jlink & org.openjfx.javafxplugin

当我在开发和测试中运行程序时(在 Windows 10 机器上),这工作正常,但是当它打包并部署在 Windows 机器上(到目前为止的任何 Windows 10)时,我得到一个java.lang.Throwable : SSL 握手失败”页面加载时的异常。

这是堆栈跟踪:

    [ERROR] 2021-07-14 14:13:53.737 [JavaFX Application Thread] MediaElementWeb - WebView Failed: 
java.lang.Throwable: SSL handshake Failed
    at javafx.scene.web.WebEngine$LoadWorker.describeError(WebEngine.java:1440) ~[javafx.web:?]
    at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1379) ~[javafx.web:?]
    at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1240) ~[javafx.web:?]
    at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2524) ~[javafx.web:?]
    at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2369) ~[javafx.web:?]
    at com.sun.webkit.network.URLLoaderBase.twkDidFail(Native Method) ~[javafx.web:?]
    at com.sun.webkit.network.URLLoader.notifyDidFail(URLLoader.java:799) ~[javafx.web:?]
    at com.sun.webkit.network.URLLoader.lambda$didFail$6(URLLoader.java:782) ~[javafx.web:?]
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447) ~[javafx.graphics:?]
    at java.security.AccessController.doPrivileged(AccessController.java:391) ~[?:?]
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446) ~[javafx.graphics:?]
    at com.sun.glass.ui.invokelaterdispatcher$Future.run(invokelaterdispatcher.java:96) ~[javafx.graphics:?]
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) ~[javafx.graphics:?]
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174) ~[javafx.graphics:?]
    at java.lang.Thread.run(Thread.java:832) [?:?]

该问题并非特定于任何特定证书,因此我知道这通常不是证书的特定问题,已在许多站点上进行了测试。我只在部署的应用程序中收到此错误

页面正在以标准方式加载:WebEngine.load(targetURL);

我正在捕获错误

tNode.getEngine().getLoadWorker().stateproperty().addListener((o,ov,nv) -> {
            if (nv == Worker.State.Failed) {
                logger.error("WebView Failed: ",tNode.getEngine().getLoadWorker().getException());
            }
        });

搜索并尝试了其他人提供的似乎遇到过类似错误解决方案,例如:

调用 load(page) 之前设置信任管理器:

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 (GeneralSecurityException e) {
            logger.error("SSLContext Failed: ",e);
        }

(这里没有错误或影响)

在部署中设置 JVMarg

-Dcom.sun.webkit.useHTTP2Loader=false

我能看到的效果是在堆栈跟踪中显示了“com.sun.webkit.network.URLLoader”而不是 http2(正如其他线程所建议的那样),但这里也没有变化。

有没有人对问题可能是什么以及如何解决有任何想法(请记住,我是 Java 桌面部署的新手)?

非常感谢

更新:

Trace from console on deployed test https://pastebin.com/R5SkR4w1

前几行:

javax.net.ssl|WARNING|2C|URL-Loader-1|2021-07-15 10:46:45.991 BST|SignatureScheme.java:295|Signature algorithm,ed25519,is not supported by the underlying providers
javax.net.ssl|WARNING|2C|URL-Loader-1|2021-07-15 10:46:45.992 BST|SignatureScheme.java:295|Signature algorithm,ed448,is not supported by the underlying providers
javax.net.ssl|WARNING|2C|URL-Loader-1|2021-07-15 10:46:45.995 BST|NamedGroup.java:297|No AlgorithmParameters for x25519 (
"throwable" : {
  java.security.NoSuchAlgorithmException: Algorithm x25519 not available
        at java.base/javax.crypto.KeyAgreement.getInstance(KeyAgreement.java:192)
        at java.base/sun.security.ssl.NamedGroup.<init>(NamedGroup.java:286)
        at java.base/sun.security.ssl.NamedGroup.<clinit>(NamedGroup.java:184)
        at java.base/sun.security.ssl.SignatureScheme.<clinit>(SignatureScheme.java:59)
        at java.base/sun.security.ssl.SSLSessionImpl.<clinit>(SSLSessionImpl.java:823)
        at java.base/sun.security.ssl.TransportContext.<init>(TransportContext.java:133)
        at java.base/sun.security.ssl.TransportContext.<init>(TransportContext.java:103)
        at java.base/sun.security.ssl.SSLSocketImpl.<init>(SSLSocketImpl.java:111)
        at java.base/sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:72)
        at java.base/sun.net.www.protocol.https.HttpsClient.createSocket(HttpsClient.java:413)
        at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:162)
        at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:474)
        at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:569)
        at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:265)
        at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:372)
        at ...

解决方法

通过@slaw 对我最初尝试但最终未正确实施的建议的有用评论,设法解决了这个问题,@dave_thompson_085 提供了有关如何提供额外调试信息的帮助。所以决议,以及对同船的人的一些提示:

1.解决办法:

Java 14 和 JavaFX 16 上 Intellij IDEA gradle 的 Badass Jlink 插件没有正确合并安全提供程序类。 这是通过将“jdk.crypto.ec”添加到合并模块列表中解决的。

2.手动添加模块

org.beryx.jlink 插件 (2.24.0) 非常复杂和强大,所以我很难弄清楚如何通过我的实现来实现。

我尝试了很多组合,但以下代码在我的 build.gradle 中为我做了:

jlink  {
    //... Other jlink \ jpackage stuff
    mergedModule {
        additive = true
        requires 'jdk.crypto.ec'
    }
    //... Other jlink \ jpackage stuff
}

3.为 Windows 调试打包的 Java 二进制文件

一些 Jlink 配置更改在此过程中有所帮助。

jlink  {
    //..
    jpackage {
        //..
        imageOptions = [
                "--win-console"
        ]
    }
    //..    
    launcher {
        jvmArgs = ['-Dcom.sun.webkit.useHTTP2Loader=false','-Djavax.net.debug=ssl:handshake']
    }

}

--win-console 在您启动程序时打开一个控制台窗口,以便您可以看到注销的内容

-Djavax.net.debug=ssl:handshake 提供有关 SSL 过程和握手的更多信息,以便您了解正在发生的事情。