JavaFX WebView не загружает страницу

Я пытаюсь открыть "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);
    }
}

JavaFX WebView не загружает страницу

Комментарий к ответу на связанный вопрос о том, как доверять всем сертификатам SSL. отмечает, что X509TrustManagergetAcceptedIssuers() Документация Javadoc требует возврата ненулевого массива. Вы возвращаете null, а не пустой массив. Возможно, эта спецификация изначально не применялась, но где-то между этими версиями Java она стала применяться. Попробуйте это изменить.
FThompson 11.09.2018 08:12

Что ж, это точно не проблема. Я попытался вернуть пустой массив, и результат тот же. Страница не отображается .. Я не получаю сообщение об ошибке SSL. Я не получаю никаких ошибок, только страница empy .. это URL-адрес, на который в последний раз перенаправлялся экран:

Radoslav Ignatov 11.09.2018 20:29
login.microsoftonline.com/common/oauth2/…
Radoslav Ignatov 11.09.2018 20:29

Я протестировал ваш код в каждом из этих четырех JDK, чтобы убедиться, что это действительно проблема JDK, а не системная проблема. Я понятия не имею, почему эта проблема возникает в некоторых JDK, а не в других. Странно.

FThompson 12.09.2018 09:26

Сравните файлы java.security в папках JRE / lib / security. У меня такое ощущение, что либо порядок security.providers был изменен (как только мы получили этот сюрприз), либо были изменены некоторые настройки, связанные с SSL.

m4gic 12.09.2018 16:41

@ m4gic Я попытался заменить папку безопасности JRE181 папкой безопасности JRE161 (действительно было несколько отличий в файлах), но это не сработало. Результат был таким же, поэтому я думаю, проблема не в папках безопасности.

Radoslav Ignatov 21.09.2018 12:37

Убедитесь, что ваша конфигурация - поддерживаемая конфигурация JavaFX, этот ссылка может быть более точным

m4gic 21.09.2018 13:38
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
1 882
1

Ответы 1

Оказалось, что ЛЮБАЯ сетевая проблема (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, она будет загружена ...

Radoslav Ignatov 21.09.2018 22:39

Хм, я не тестировал решение с вашим URL. Я делал это дома, и кажется, что этот сайт использует Oauth2 и, возможно, фреймы, любой из них, или, возможно, javascript является причиной, по которой он не работает (у меня есть только ноль). здесь вы можете прочитать сравнение доступных браузеров для java, возможно вам стоит перейти на другую реализацию. Другой вариант - выполнить oauth2 вручную, но я думаю, что это было бы слишком болезненно.

m4gic 22.09.2018 01:01

Другие вопросы по теме