Wednesday 20 January 2016

How to load HTTPS url from Java FX Webview component?

JavaFx has WebView component that can be used to load the Http & Https Url.
The basic steps to load any url using WebView is

WebView view = new WebView();
engine = view.getEngine();
engine.load(new URL("http://www.google.com));
engine.load(new URL("https://mail.google.com));

The problem comes when we have Https url to be loaded.
If the https url that we want to load have signed certificate, we can easily load it.
But if https url that we want to load does not have a signed certificate, it becomes difficult to load the Url.

To solve this, we disable the certificate check and mark the connection object to trust all the certificates.

Below is the code snippet that you should write just before loading the URL.

 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) {  
     }  

To create a full embeded browser that is able to load urls having self signed certificates.

 package utility;  
 import javafx.application.Platform;  
 import javafx.beans.value.ChangeListener;  
 import javafx.beans.value.ObservableValue;  
 import javafx.concurrent.Worker;  
 import javafx.embed.swing.JFXPanel;  
 import javafx.event.EventHandler;  
 import javafx.scene.Scene;  
 import javafx.scene.web.WebEngine;  
 import javafx.scene.web.WebEvent;  
 import javafx.scene.web.WebView;  
 import javax.net.ssl.HttpsURLConnection;  
 import javax.net.ssl.SSLContext;  
 import javax.net.ssl.TrustManager;  
 import javax.net.ssl.X509TrustManager;  
 import javax.swing.*;  
 import java.awt.*;  
 import java.net.MalformedURLException;  
 import java.net.URL;  
 import java.security.GeneralSecurityException;  
 import static javafx.concurrent.Worker.State.FAILED;  
 public class SimpleWebBrowser extends JFrame {  
   private final JFXPanel jfxPanel = new JFXPanel();  
   private WebEngine engine;  
   private final JPanel panel = new JPanel(new BorderLayout());  
   private final JLabel lblStatus = new JLabel();  
   private final JProgressBar progressBar = new JProgressBar();  
   public SimpleWebBrowser() {  
     super();  
     initComponents();  
   }  
   private void initComponents() {  
     createScene();  
     progressBar.setPreferredSize(new Dimension(150, 18));  
     progressBar.setStringPainted(true);  
     JPanel topBar = new JPanel(new BorderLayout(5, 0));  
     topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));  
     JPanel statusBar = new JPanel(new BorderLayout(5, 0));  
     statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));  
     statusBar.add(lblStatus, BorderLayout.CENTER);  
     statusBar.add(progressBar, BorderLayout.EAST);  
     panel.add(topBar, BorderLayout.NORTH);  
     panel.add(jfxPanel, BorderLayout.CENTER);  
     panel.add(statusBar, BorderLayout.SOUTH);  
     getContentPane().add(panel);  
     setPreferredSize(new Dimension(1024, 600));  
     pack();  
   }  
   private void createScene() {  
     Platform.runLater(new Runnable() {  
       @Override  
       public void run() {  
         WebView view = new WebView();  
         engine = view.getEngine();  
         engine.titleProperty().addListener(new ChangeListener<String>() {  
           @Override  
           public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {  
             SwingUtilities.invokeLater(new Runnable() {  
               @Override  
               public void run() {  
                 SimpleWebBrowser.this.setTitle(newValue);  
               }  
             });  
           }  
         });  
         engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {  
           @Override  
           public void handle(final WebEvent<String> event) {  
             SwingUtilities.invokeLater(new Runnable() {  
               @Override  
               public void run() {  
                 lblStatus.setText(event.getData());  
               }  
             });  
           }  
         });  
         engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {  
           @Override  
           public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {  
             SwingUtilities.invokeLater(new Runnable() {  
               @Override  
               public void run() {  
                 progressBar.setValue(newValue.intValue());  
               }  
             });  
           }  
         });  
         engine.getLoadWorker()  
             .stateProperty()  
             .addListener(new ChangeListener<Worker.State>() {  
               @Override  
               public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State state, Worker.State state2) {  
                 if(state2 == Worker.State.SUCCEEDED){  
                   System.out.println("Completed");  
                 }  
               }  
             });  
         engine.getLoadWorker()  
             .exceptionProperty()  
             .addListener(new ChangeListener<Throwable>() {  
               public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {  
                 if (engine.getLoadWorker().getState() == FAILED) {  
                   SwingUtilities.invokeLater(new Runnable() {  
                     @Override public void run() {  
                       JOptionPane.showMessageDialog(  
                           panel,  
                           (value != null) ?  
                               engine.getLocation() + "\n" + value.getMessage() :  
                               engine.getLocation() + "\nUnexpected error.",  
                           "Loading error...",  
                           JOptionPane.ERROR_MESSAGE);  
                     }  
                   });  
                 }  
               }  
             });  
         jfxPanel.setScene(new Scene(view));  
       }  
     });  
   }  
   public void loadURL(final String url) {  
     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) {  
     }  
     Platform.runLater(new Runnable() {  
       @Override  
       public void run() {  
         String tmp = toURL(url);  
         if (tmp == null) {  
           tmp = toURL("http://" + url);  
         }  
         engine.load(tmp);  
       }  
     });  
   }  
   private static String toURL(String str) {  
     try {  
       return new URL(str).toExternalForm();  
     } catch (MalformedURLException exception) {  
       return null;  
     }  
   }  
   public static void main(String[] args) {  
     SwingUtilities.invokeLater(new Runnable() {  
       public void run() {  
         SimpleWebBrowser browser = new SimpleWebBrowser();  
         browser.setVisible(true);  
         browser.loadURL("https://self-sgned-url.com");  
         try {  
           Thread.sleep(5000);  
         } catch (InterruptedException e) {  
           e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.  
         }  
       }  
     });  
   }  
 }  

Done.

2 comments:

  1. Thanks for your article, it is very comprehensive. If possible you can do more tutorials by keystore with https pass javafx

    ReplyDelete
  2. Such a very useful article. Very interesting to read this article.I would like to thanks for sharing.If you are looking for best Oracle online training, we provide the low price of fee for on-line coaching.
    Oracle fusion financials training

    ReplyDelete