Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

JVM Languages

Java Q&A


Java Q&A

Kenneth is a senior software engineer for American Management Systems. Thomas is a technical architect in the corporate banking practice at American Management Systems. They can be contacted at kenneth_ [email protected] and thomas_ [email protected], respectively.


One of the significant features of Java is its simple implementation of networking classes. This streamlined but powerful collection of classes lets Java applets easily open sockets to servers and transmit data. Ensuring that the data transmitted over a socket is safe from prying eyes is not as simple, however.

The Secure Sockets Layer (SSL) protocol, developed by Netscape, is the de facto standard for sending encrypted data over the Internet. SSL provides a platform-independent way to secure data transmitted from one machine to another. On the Web, safe communications are denoted by the HTTPS protocol (meaning that a server listens for data with an SSL socket). This ensures that all communications between the browser and web server are encrypted, and that the server has been authenticated. In a case where web browsers have a certificate to prove the identity of its user, SSL also provides for client-side authentication.

Java applets can implement SSL in two different ways. The most obvious, and more difficult, way is to acquire an implementation of the SSL protocol written in Java. This implementation would provide a Secure Socket class that would operate in the same manner as a standard Java Socket, only the data would now be encrypted before transmission. While relatively simple from a technical standpoint, this option requires buying a commercially available Java implementation of SSL, and getting the appropriate licensing for distribution over the Web. Furthermore, the web browser needs to download the Java class files for the Secure Socket every time the applet is run, adding to the time it takes for the applet to start up. In addition, the code to perform these services is already provided by the web browser. This code is written in a native compiled language and has been time tested for optimal performance. Supplying this functionality in Java is inefficient and repetitive.

The second, less obvious, option utilizes the Secure Socket functionality already built into web browsers and web servers by tunneling proprietary data over the HTTPS protocol. Tunneling is the process of transmitting data of one protocol type by wrapping it in a stream of a second protocol.

At American Management Systems, we've experimented with HTTPS tunneling to pass data from a Java applet to an application server and determined that its benefits include:

  • The method uses industry-accepted and tested security procedures.
  • The native implementation of SSL is more efficient than a Java implementation.
  • HTTPS tunneling facilitates communication through firewalls. (Corporate firewalls often have HTTPS Port 443 open for access to the Internet. Access to any other port is difficult to control on the client side.)
  • The certificates that are installed in the web browser/web server are utilized. There is no need for separate certificates.

Digging a Secure Tunnel

There are three aspects to the tunneling process you need to consider -- the Java Applet Client, Proxying Service, and Application Server.

Java Applet Client. The applet client is responsible for instructing the browser to send data over the HTTPS URL. The listener will receive data that is posted to the URL https://Servlets/ProxyServlet. HTTPS URLs basically function like regular sockets as a means to transmit data, with these exceptions:

  • The data must be encoded to the x-www-form-urlencoded MIME format before it is sent to the URL. URL encoding replaces spaces with "+" characters and changes all nonalphanumeric characters to a three-character representation.
  • Data carried over an HTTPS URL comes in one of two varieties, POST and GET. An HTTP GET sends additional data to the server as a query string appended to the URL (denoted by a question mark). A POST sends the data as a separate blob. In this case, the POST is preferred. Unlike a GET, a POST is not restricted to any size, and it provides a content-length property that makes reading from the stream much simpler.
  • A feature of many browsers is that they can cache requests for a given URL. They can then return the cached data without consulting the server if the same URL is requested twice. Clearly this has the potential to cause problems in a client/server application. Fortunately, there is a method (setUseCaches) to turn this off.
  • Unlike sockets, URLs are not connection oriented. This means that the connections are opened when they are needed and close immediately after they are read. Most browsers and web servers support the HTTP keep-alive specification, which can alleviate the overhead of renegotiating a socket connection for every send. This is accomplished by keeping the connections open for a server-specified time-out even after an application tries to close them. Those connections are reused if an attempt is made to reconnect within the time-out; see Example 1.

Once these considerations are made, URL connections can operate just like regular sockets. A program can retrieve an output stream to send data and an input stream to read the response.

Listing One is an applet that opens a URL connection using the HTTPS protocol. The applet sets the appropriate parameters on the connection object, sends the string, and reads and prints out the response. Listing Two (ClientExample.html) calls the applet from within an HTML document.

Proxying Service. One of the security features of the Java environment is that downloaded applets can only communicate back to the machine from which they were downloaded. This makes it impossible for a Java client to communicate directly to any server sitting anywhere outside of the web server. A proxying service must be created to intercept the data on the web server and forward it onto a predefined server, facilitating the communications between the client and the server. This service is responsible for:

  • Receiving the request data from the client over the HTTPS protocol.
  • Passing the data onto a predefined server address using a standard socket connection.
  • Waiting for the server to respond to the request.
  • Receiving the data from the server over the socket connection.
  • Passing the data back to the client over the HTTPS protocol.

The proxy service can be implemented utilizing any native web server plug-in facility such as CGI, NSAPI on Netscape Servers, ISAPI on Microsoft IIS, or the Java Servlet API. This implementation uses a Java Servlet installed on the web server. Figure 1 shows how the Client/ProxyServlet/Server interact. The client POSTs the data to the ProxyServlet URL (https://Servlets/ProxyServlet) and waits for a response. The web server is configured to pass this data into the Java ProxyServlet for processing. The ProxyServlet URL decodes the posted data, creates a socket connection through a firewall to the Application Server, transmits the data over the socket, and waits for a response. The firewall is configured to allow communication only between the web server and the Application Server to secure the data behind the firewall. The Application Server receives the request data, processes the request, and sends the response data back to the ProxyServlet. The ProxyServlet receives the response data and returns it as a response to the POST. The Java Client Applet receives the response to the URL request and processes the response.

ProxyServlet.java and ServerConnection.java (available electronically; see "Resource Center," page 3) implement the Java ProxyServlet. This implementation will create a new connection to the Application Server for each client request. The Servlet.properties file (see Listing Three) contains parameters for serverPort and serverAddress. These parameters configure the destination TCP/IP address of the application server. An enhancement to this architecture would be to add a connection manager that would maintain a pool of connections to the application server. This enhancement would remove the overhead of creating a new connection to the Application Server for each request that is processed, thus improving performance.

Application Server. The Application Server is a standard TCP/IP server implementation. The Application Server listens on a defined port, receives the request data over the socket, processes the request and creates response data, then passes this data back over the socket. This is a common architecture, and examples can be easily found that are implemented in Java or C++.

Issues

This solution is not 100 percent pure Java because of its reliance on the browser's implementation of the HTTPS protocol. Since all of major browsers support the secure protocol, this is not a serious issue.

Current limitations in Microsoft's Internet Explorer 4.0x cause problems when a Java applet uses URL Connections. This problem can be alleviated by disabling the HTTP 1.1 option on either the browser or the web server. (This issue may already be resolved by the time you read this.)

Conclusion

While using the socket classes provided by Java for communications can be simple, when introducing real-world issues, such as security and firewalls, their usability can fall short. HTTPS tunneling provides SSL security and consideration for firewalls. When contrasted with a Java implementation of SSL, tunneling over HTTPS decreases your code size and provides significant performance improvement.

DDJ

Listing One

/* ClientExample.java -- @version 1.0 * @author American Management Systems
 * Opens a connection to the specified URL using the HTTPS protocol
 * sends data that is passed as a parameter then reads the server response
 */


</p>
import java.applet.*;
import java.net.*;
import java.io.*;


</p>
public class ClientExample extends Applet {


</p>
   //The instance of the url connection
   private URLConnection urlConnection;


</p>
   /** Starts the applet this is called every time the page is reloaded */
   public void start() {
      System.out.println("ClientExample sends data to a 
                                               server using HTTPS POST");
      String data = getParameter("Data");


</p>
      send(data);
      read();
   }
   /** This is called to send the data over a new URL */
   public void send(String data) {
      try {
         System.out.println("Data: " + data);


</p>
         //URL encode the data to the x-www-form-urlencoded MIME format
         String urlEncodedData = URLEncoder.encode(data);
         System.out.println("URL Encoded Data: " + urlEncodedData);


</p>
         //Instance the URL (protocol, host, port)
         String protocol = getCodeBase().getProtocol();
         int  port = getCodeBase().getPort();
         String host = getCodeBase().getHost();
         URL url = new URL(protocol, host, port, "/servlet/ProxyServlet");
         System.out.println("Destination URL: " + url.toString());


</p>
         //Open the connection
         urlConnection = url.openConnection();


</p>
         //Turn off the caching feature
         urlConnection.setUseCaches(false);


</p>
         //Set the URL to POST instead of GET
         urlConnection.setDoOutput(true);


</p>
         //Set necessary properties
         urlConnection.setRequestProperty("content-type", 
                                    "application/x-www-form-urlencoded");
         urlConnection.setRequestProperty("content-length", 
                                String.valueOf(urlEncodedData.length()));


</p>
         //Get the output stream and send the data
         PrintStream outStream = 
                         new PrintStream(urlConnection.getOutputStream());
         outStream.println(urlEncodedData);
         outStream.close();
         System.out.println("Data sent successfully");
      }
         catch(Exception e) {
            System.out.println("URL Connection error: " + e.toString());
         }
    }


</p>
   /** This is called to read the response from the server */
   public void read() {
      try {
         //Get the input stream from the connection object
         DataInputStream in = 
                     new DataInputStream(new 
                     BufferedInputStream(urlConnection.getInputStream()));
         //Read a line of data
         String response = in.readLine();
         System.out.println("Server response: " + response);
      }
         catch(IOException e) {
           System.out.println("Error reading from input stream " 
                                                           + e.toString());
         }
   }
}

Back to Article

Listing Two

<html><head>
<title>ClientExample</title>
</head>


</p>
<body>
Check to the java console for output
<hr>


</p>
<applet code=ClientExample.class width=40 height=40>
<param name=Data value=ClientExample data>
</applet>


</p>
<hr>
</body>
</html>

Back to Article

Listing Three

servlet.ProxyServlet.code=ProxyServletservlet.ProxyServlet.initArgs=serverPort=4321,serverAddress=127.0.0.1

Back to Article


Copyright © 1998, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.