问题描述
我正在将一个 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 过程和握手的更多信息,以便您了解正在发生的事情。