JDK Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 4.32, 2006

SSL - HTTPS

Part:   1  2  3  4  

JDK Tutorials - Herong's Tutorial Notes © Dr. Herong Yang

Internationalization

Character Set and Encoding

Socket Communication

Document Object Model (DOM)

XSD Validation in Java

XSL - Transformer in Java

JCA - Private and Public Key Pairs

JCE - Secret Key

SSL (Secure Socket Layer)

SSL - Client Authentication

... Table of Contents

(Continued from previous part...)

A Better HTTPS Server - HttpsEchoer.java

Based on the experience from previous examples, I wrote a better HTTPS server, HttpsEchoer.java. It will handle the abandoned connections correctly. Of course, it will echo the HTTP request back to the client.

/**
 * HttpsEchoer.java
 * Copyright (c) 2005 by Dr. Herong Yang
 */
import java.io.*;
import java.security.*;
import javax.net.ssl.*;
public class HttpsEchoer {
   public static void main(String[] args) {
      String ksName = "herong.jks";
      char ksPass[] = "HerongJKS".toCharArray();
      char ctPass[] = "My1stKey".toCharArray();
      try {
         KeyStore ks = KeyStore.getInstance("JKS");
         ks.load(new FileInputStream(ksName), ksPass);
         KeyManagerFactory kmf = 
         KeyManagerFactory.getInstance("SunX509");
         kmf.init(ks, ctPass);
         SSLContext sc = SSLContext.getInstance("TLS");
         sc.init(kmf.getKeyManagers(), null, null);
         SSLServerSocketFactory ssf = sc.getServerSocketFactory();
         SSLServerSocket s 
            = (SSLServerSocket) ssf.createServerSocket(8888);
         System.out.println("Server started:");
         printServerSocketInfo(s);
         // Listening to the port
         int count = 0;
         while (true) {
            SSLSocket c = (SSLSocket) s.accept();
            // Someone is calling this server
            count++;
            System.out.println("Connection #: "+count);
            printSocketInfo(c);
            BufferedWriter w = new BufferedWriter(
               new OutputStreamWriter(c.getOutputStream()));
            BufferedReader r = new BufferedReader(
               new InputStreamReader(c.getInputStream()));
            String m = r.readLine();
            if (m!=null) {
               // We have a real data connection
               w.write("HTTP/1.0 200 OK");
               w.newLine();
               w.write("Content-Type: text/html");
               w.newLine();
               w.newLine();
               w.write("<html><body><pre>");
               w.newLine();
               w.write("Connection #: "+count);
               w.newLine();
               w.newLine();
               w.write(m);
               w.newLine();
               while ((m=r.readLine())!= null) {
                  if (m.length()==0) break; // End of a GET call
                  w.write(m);
                  w.newLine();
               }
               w.write("</pre></body></html>");
               w.newLine();
               w.flush();
            }     
            w.close();
            r.close();
            c.close();
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
   private static void printSocketInfo(SSLSocket s) {
      System.out.println("Server socket class: "+s.getClass());
      System.out.println("   Remote address = "
         +s.getInetAddress().toString());
      System.out.println("   Remote port = "
         +s.getPort());
      System.out.println("   Local socket address = "
         +s.getLocalSocketAddress().toString());
      System.out.println("   Local address = "
         +s.getLocalAddress().toString());
      System.out.println("   Local port = "
         +s.getLocalPort());
   }
   private static void printServerSocketInfo(SSLServerSocket s) {
      System.out.println("Server socket class: "+s.getClass());
      System.out.println("   Socker address = "
         +s.getInetAddress().toString());
      System.out.println("   Socker port = "
         +s.getLocalPort());
      System.out.println("   Need client authentication = "
         +s.getNeedClientAuth());
      System.out.println("   Want client authentication = "
         +s.getWantClientAuth());
      System.out.println("   Use client mode = "
         +s.getUseClientMode());
   } 
}

Now run HttpsEchoer in a command window, and run IE with https://localhost:8888/hello.html. IE will still display two security alerts as before. But HttpsEchoer will handle the IE's requests correctly. You will get the following in the IE window:

Connection #: 2

GET /hello.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appli...
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NE...
Host: localhost:8888
Connection: Keep-Alive

Note that connection count is 2 not 1. This confirms my notes about IE's behavior in the previous section. Connection 1 was closed by IE when it failed validate the certificate and displayed the second security alert.

If you look at the HttpsEchoer window, you will see 2 connections recorded:

Server started:
Server socket class: 
   class com.sun.net.ssl.internal.ssl.SSLServerSocketImpl
   Socker address = 0.0.0.0/0.0.0.0
   Socker port = 8888
   Need client authentication = false
   Want client authentication = false
   Use client mode = false
Connection #: 1
Server socket class: class com.sun.net.ssl.internal.ssl.SSLSocketImpl
   Remote address = /127.0.0.1
   Remote port = 2025
   Local socket address = /127.0.0.1:8888
   Local address = /127.0.0.1
   Local port = 8888
   Need client authentication = false
   Cipher suite = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
   Protocol = SSLv3
Connection #: 2
Server socket class: class com.sun.net.ssl.internal.ssl.SSLSocketImpl
   Remote address = /127.0.0.1
   Remote port = 2026
   Local socket address = /127.0.0.1:8888
   Local address = /127.0.0.1
   Local port = 8888
   Need client authentication = false
   Cipher suite = SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
   Protocol = SSLv3

Conclusion

  • HTTPS is HTTP running on top of SSL. You can write HTTPS server and client programs like any other SSL socket programs.
  • When IE connects to a HTTPS server, and gets an invalid certificate, it will abandon the connection. HTTPS server program needs to be smart to handle this.

Part:   1  2  3  4  

Dr. Herong Yang, updated in 2006
JDK Tutorials - Herong's Tutorial Notes - SSL - HTTPS