|
SSL - HTTPS
Part:
1
2
3
4
(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
|