Я пытаюсь открыть "engine.load (" https://login.microsoftonline.com ");" в JavaFX WebView.
При использовании jdk1.8.0_161 страница загружается. При использовании jdk1.8.0_181 страница не загружается. Он отображает пустое окно и не возвращает никаких ошибок: engine.getLoadWorker (). exceptionProperty () имеет значение null.
Вы знаете, что могло измениться в обновлениях новой версии Java? Я тестировал последнюю версию Java 10, и страница также не загружается. Этот код работает с JDK8.161 и JDK9.0.4, но не работает с JDK8.181 и JDK10.0.2.
Вот исходный код созданного мной примера приложения:
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebErrorEvent;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javafx.util.Callback;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.swing.*;
import org.w3c.dom.Document;
public class LoginApplicationWindow {
public static void main(String args[]) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(620, 440);
final JFXPanel fxpanel = new JFXPanel();
frame.add(fxpanel);
Platform.runLater(new Runnable() {
@Override
public void run() {
WebEngine engine;
WebView wv = new WebView();
engine = wv.getEngine();
engine.setJavaScriptEnabled(true);
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
}};
// Install the all-trusting trust manager
SSLContext sc;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// TODO Auto-generated method stub
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
public void changed(ObservableValue ov, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
Document doc = engine.getDocument();
// operations on dom occur here.
System.out.println(engine.getLoadWorker().exceptionProperty());
System.out.print("load finished " + doc.getBaseURI());
}
}
});
engine.setOnAlert(new EventHandler<WebEvent<String>>() {
@Override
public void handle(WebEvent<String> event) {
System.out.print("setOnAlert " + event.getData());
}
});
engine.setOnError(new EventHandler<WebErrorEvent>() {
@Override
public void handle(WebErrorEvent event) {
System.out.print("onError " + event.getMessage());
}
});
engine.setConfirmHandler(new Callback<String, Boolean>() {
@Override
public Boolean call(String param) {
// TODO Auto-generated method stub
System.out.print("setConfirmHandler " + param);
return null;
}
});
fxpanel.setScene(new Scene(wv));
engine.load("https://login.microsoftonline.com");
//engine.load("https://facebook.com");
}
});
frame.setVisible(true);
}
}
Что ж, это точно не проблема. Я попытался вернуть пустой массив, и результат тот же. Страница не отображается .. Я не получаю сообщение об ошибке SSL. Я не получаю никаких ошибок, только страница empy .. это URL-адрес, на который в последний раз перенаправлялся экран:
Я протестировал ваш код в каждом из этих четырех JDK, чтобы убедиться, что это действительно проблема JDK, а не системная проблема. Я понятия не имею, почему эта проблема возникает в некоторых JDK, а не в других. Странно.
Сравните файлы java.security в папках JRE / lib / security. У меня такое ощущение, что либо порядок security.providers был изменен (как только мы получили этот сюрприз), либо были изменены некоторые настройки, связанные с SSL.
@ m4gic Я попытался заменить папку безопасности JRE181 папкой безопасности JRE161 (действительно было несколько отличий в файлах), но это не сработало. Результат был таким же, поэтому я думаю, проблема не в папках безопасности.
Убедитесь, что ваша конфигурация - поддерживаемая конфигурация JavaFX, этот ссылка может быть более точным




Оказалось, что ЛЮБАЯ сетевая проблема (DNS / соединение) может вызвать ошибку, и загрузка не вызовет правильного исключения. Хорошая новость заключается в том, что если вы замените вызов .load (url), по крайней мере, вы увидите проблемы в журнале.
При замене я имею в виду, что загружаю сайт отдельно в String
private static String getData(String address) throws Exception {
URL page = new URL(address);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
try (InputStreamReader in = new InputStreamReader(
(InputStream) conn.getContent())) {
BufferedReader buff = new BufferedReader(in);
String line;
do {
line = buff.readLine();
text.append(line + "\n");
} while (line != null);
return text.toString();
} finally {
conn.disconnect();
}
}
И замените .load:
//engine.load("https://login.microsoftonline.com");
engine.loadContent(getData("https://login.microsoftonline.com"));
Конечно, исключение должно быть правильно зафиксировано и зарегистрировано. (Забавно то, что ресурсы, на которые есть ссылки (изображения / js / css, любые файлы), также будут хорошо загружены таким образом.)
Так что это не проблема SSL. Я попытался загрузить контент в виде строки, и у меня это получилось. Но когда я пытаюсь разместить его в веб-просмотре с помощью loadContent, я получаю пустой экран. Если я установлю любую другую допустимую строку HTML в loadContent, она будет загружена ...
Хм, я не тестировал решение с вашим URL. Я делал это дома, и кажется, что этот сайт использует Oauth2 и, возможно, фреймы, любой из них, или, возможно, javascript является причиной, по которой он не работает (у меня есть только ноль). здесь вы можете прочитать сравнение доступных браузеров для java, возможно вам стоит перейти на другую реализацию. Другой вариант - выполнить oauth2 вручную, но я думаю, что это было бы слишком болезненно.
X509TrustManagergetAcceptedIssuers()Документация Javadoc требует возврата ненулевого массива. Вы возвращаетеnull, а не пустой массив. Возможно, эта спецификация изначально не применялась, но где-то между этими версиями Java она стала применяться. Попробуйте это изменить.