Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

Servlets, Session Tracking Using Basic Authentication

Java Programming, Lecture Notes # 695, Revised 3/27/99.

Preface

Introduction

Sample Program

Interesting Code Fragments

Program Listing


Preface

Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the spring semester of 1999.

This lesson was originally written on March 27, 1999.

The sample servlet in this lesson was tested using Win95, Netscape Navigator, the JDK 1.2 download package from JavaSoft, the JSDK 2.0 download package from JavaSoft, and the Jigsaw web server that, as of 3/27/99, was freely available from http://www.w3.org/Jigsaw/. The sample program was tested using Jigsaw from the same machine, and also from a different machine on the network.

Introduction

This is one of a series of lessons designed to show you various ways to implement session tracking using servlets. The purpose of the lesson is to illustrate session tracking using the Basic Authentication capability provided by most HTTP web servers.

An HTTP server that provides Basic Authentication capability has the capability to maintain a list of user names and passwords. It also has the capability to protect resources (directories, files, servlets, etc.) making those resources available only to specified users.

The manner in which the list of user names and passwords is maintained, and the manner in which resources are protected, differs from one server to the next. For the sample program in this lesson, I used the administrator features of the Jigsaw server to establish the list and the protection. You will need to see your server documentation for more information on this topic.

When a resource is protected and a user attempts to access it, the server requires to the client to provide the user's name and password. The browser obtains the name and password from the user and provides it to the server. If that user is authorized to access the requested resource, the request is granted.

Thereafter, the browser remembers and resends the name and the password as the user views different pages on the same site. This continues until the user moves on to a new site or exits the browser. If the user comes back to the site before exiting the browser, the process of sending the name and password resumes.

After the user logs in by providing the name and password to the browser, the user name is available to the servlet through the getRemoteUser() method. Assuming that the user name is unique, it can be used as a key to persistent storage (such as a database) for the purpose of maintaining information about the session.

Sample Program

The name of the servlet discussed below is Servlet13A. This is one of a group of three similar servlets named:

These three servlets are designed to work together to illustrate session tracking using Basic Authentication.

In my case, the server was set up to protect all three servlets by protecting the directory in which they are stored. (It is also possible to protect individual servlets and individual files.) The list of users having access to the servlets in the protected directory was set up to include the user named dick.

When the client makes a request to invoke one of the servlets, the server requires the client to provide a name and password. The server compares the name and password to the list of valid name/password combinations maintained in the database by the server. If the name/password combination is not valid, the client gets another opportunity to provide a name and password.

If the name/password combination is valid, the server compares the name to the list of names established as having access to the directory containing the servlet. If the name matches one of the names on that list, the servlet is invoked on behalf of the client.

When one of the servlets is invoked, it produces an output similar to the following on the client screen (only the name of the servlet differs from one servlet to the next):

Welcome to Servlet13A 
Hello dick
Authentication Type: Basic
Authorization: Basic ZGljazpkcm93c3NhcA==
Unencoded name and password: dick:drowssap
Please visit these other servlets:
Servlet13A
Servlet13B
Servlet13C

The fourth line shows an encoded version of the name and password passed over the Internet. I will discuss the encoding scheme in more detail in a subsequent lesson on servlet security (for now, suffice it to say that it is not very secure). The fifth line shows the user name and password after it has been decoded by the servlet.

The last three lines in the output are hyperlinks to each of the three servlets. Having invoked any one of the three servlets, the user can again invoke any one of the three. No matter which one is invoked, the servlet is able to identify the user and to get his name and password.

Interesting Code Fragments

The first fragment shows the beginning of the controlling class and the beginning of the doGet() method.

The fragment also shows the typical HTML boilerplate necessary to create an HTML page to be sent to the client. You have seen material such as this many times before.

public class Servlet13A extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("<HTML>");
    out.println("<HEAD><TITLE=Servlet13A</TITLE></HEAD>");
    out.println("<BODY>");
    
    out.println("Welcome to Servlet13A <BR>");

The next fragment uses the getRemoteUser() method to get and display the name of the remote user. Note that the user name is available without performing any special decoding of the incoming information.

    out.println("Hello " + req.getRemoteUser() + "<BR>");

Once the user has logged in, this name is available to servlets on this server until the user exits the browser. Therefore, it is important for the user to exit the browser when the session has been completed.

The next fragment gets and displays the type of authentication being used by the server.

    out.println("Authentication Type: " 
                             + req.getAuthType() + "<BR>");

In this case, the type is Basic Authentication. Some servers also support a more secure form of authentication known as Digest Authentication.

The next fragment shows the use of the getHeader() method to get and display the authorization string in its encoded format.

    String auth = req.getHeader("Authorization");
    out.println("Authorization: " + auth + "<BR>");

Note that the string "Authorization" is passed to the method in order to get the authorization string. Other kinds of information is also available through the getHeader() by passing different parameters.

Recall from above that the value of the authorization string displayed was:

Basic ZGljazpkcm93c3NhcA==

The boldface portion of this string contains an encoded version of the user name and password. There is no simple method available for extracting the password as is the case with the name, but it isn't particularly difficult to extract. The next fragment

    String encodedNamePassword = auth.substring(6);
    sun.misc.BASE64Decoder dec = 
                              new sun.misc.BASE64Decoder();
    String unencodedNamePassword = 
         new String(dec.decodeBuffer(encodedNamePassword));
    out.println("Unencoded name and password: " 
                         + unencodedNamePassword + "<BR>");

In my case, the unencoded version is displayed as

dick:drowssap

This is the information that you could use as a key in persistent storage (such as a database) to maintain information about the session.

I plan to discuss the unencoding mechanism in a subsequent lesson on servlet security, so I will simply show you how to do it at this point without further discussion.

The next fragment creates hyperlinks for all three of the servlets allowing the user to navigate among the different servlets at will. It is important to note that each time the user invokes any one of these servlets prior to exiting the browser, the name and password information for that user will be available as shown above.

    out.println("Please visit these other servlets:<BR>");

    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13A\">Servlet13A</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13B\">Servlet13B</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13C\">Servlet13C</A>" + "<BR>");

The remaining code (not shown here) is the boilerplate necessary to close out the HTML page. You can view that code in the next section.

Program Listing

A complete listing of one of the servlets follows. The other two servlets are identical to this one with the exception of the servlet name, so they aren't shown here.

/*File Servlet13A.java, Copyright 1999, R.G.Baldwin
Rev 3/25/99
This is one of a group of three servlets:
Servlet13A
Servlet13B
Servlet13C

that are designed to illustrate session tracking using 
BASIC AUTHENTICATION.

All three servlets are protected by the server.  When the
user requests the server to invoke one of the servlets,
the server requires the user to provide a name and 
password.  That name and password is compared, by the
server, to the set of name/password combinations maintained
in a database by the server.

If the name/password combination is valid, the server
compares the name to the list of names established by
the server administrator as being allowed access to the
servlet.  If the name matches one of the names on that
list, the servlet is invoked on behalf of the client.

When the servlet is invoked, it produces an output
similar to the following on the client screen:
  
Welcome to Servlet13A 
Hello dick
Authentication Type: Basic
Authorization: Basic ZGljazpkcm93c3NhcA==
Unencoded name and password: dick:drowssap
Please visit these other servlets:
Servlet13A
Servlet13B
Servlet13C

where the last three lines are hyperlinks to each of the
three servlets.

The servlet was tested using the JDK 1.2 download package
from JavaSoft along with the Java Servlet Development Kit
(JSDK) 2.0 from JavaSoft and the Jigsaw web server. All 
tests were performed under Win95.

**********************************************************/
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Servlet13A extends HttpServlet{
  public void doGet(HttpServletRequest req, 
                    HttpServletResponse res)
                      throws ServletException, IOException{
    res.setContentType("text/html");
    PrintWriter out = res.getWriter();
    out.println("<HTML>");
    out.println("<HEAD><TITLE=Servlet13A</TITLE></HEAD>");
    out.println("<BODY>");
    
    out.println("Welcome to Servlet13A <BR>");

    out.println("Hello " + req.getRemoteUser() + "<BR>");
    out.println("Authentication Type: " 
                             + req.getAuthType() + "<BR>");
    String auth = req.getHeader("Authorization");
    out.println("Authorization: " + auth + "<BR>");
    String encodedNamePassword = auth.substring(6);
    sun.misc.BASE64Decoder dec = 
                              new sun.misc.BASE64Decoder();
    String unencodedNamePassword = 
         new String(dec.decodeBuffer(encodedNamePassword));
    out.println("Unencoded name and password: " 
                         + unencodedNamePassword + "<BR>");
    out.println("Please visit these other servlets:<BR>");

    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13A\">Servlet13A</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13B\">Servlet13B</A>" + "<BR>");
    out.println("<A HREF=\"http://baldwin:8001/servlets"
                + "/Servlet13C\">Servlet13C</A>" + "<BR>");


    out.println("</font></h1>");
    out.println("</BODY></HTML>");
  }//end doGet()
}//end class Servlet13A

-end-