How do I use Form authentication with Tomcat?
Author: Deron Eriksson
Description: This tutorial describes the use of Form authentication with Tomcat.
Tutorial created using: Windows XP || JDK 1.5.0_09 || Eclipse Web Tools Platform 1.5.1 || Tomcat 5.5.20


Page:    1 2 3 >

In another tutorial, we set up TomcatSW with SSL with a self-signed certificate. Since we set this up, this tutorial will use SSL, since it is concerned with authentication, which typically should use encrypted communication.

Basic authentication's pop-up window is fine but not exactly pretty. Form authentication allows you to specify an htmlW file (or jspW) to go for authentication. You can also specify a file to go to if authentication fails. The demonstration project is called 'tomcat-demo'. It has a web.xmlW file, a login.html file, a login-failed.html file, and a TestServlet class.

Eclipse Navigator View

The web.xml file is shown below. Notice that login-config → auth-method specifies FORM since we want to use Form authentication. Note that form-login-page points to our login.html file in our web directory, and form-error-page points to our login-failed.html file. Of further interest is the transport-guarantee value, which is CONFIDENTIAL. This causes a request for a protected resource on a non-secure port to be redirected to a secure port. This allows us to authenticate securely with HTTPS even if the initial request is to the HTTP port.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="tomcat-demo" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<servlet>
		<servlet-name>TestServlet</servlet-name>
		<servlet-class>test.TestServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>TestServlet</servlet-name>
		<url-pattern>/test</url-pattern>
	</servlet-mapping>

	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Wildcard means whole app requires authentication</web-resource-name>
			<url-pattern>/*</url-pattern>
			<http-method>GET</http-method>
			<http-method>POST</http-method>
		</web-resource-collection>

		<auth-constraint>
			<role-name>tomcat</role-name>
		</auth-constraint>

		<user-data-constraint>
			<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
			<transport-guarantee>CONFIDENTIAL</transport-guarantee>
		</user-data-constraint>
	</security-constraint>

	<login-config>
		<auth-method>FORM</auth-method>
		<form-login-config>
			<form-login-page>/login.html</form-login-page>
			<form-error-page>/login-failed.html</form-error-page>
		</form-login-config>
	</login-config>
</web-app>

The login.html file contains a form with j_security_check as its action. It contains a text input called j_username and a password input called j_password. These are the input names that need to be used in order for Tomcat to process the Form authentication.

login.html

<form method="POST" action="j_security_check">
<table>
	<tr>
		<td colspan="2">Login to the Tomcat-Demo application:</td>
	</tr>
	<tr>
		<td>Name:</td>
		<td><input type="text" name="j_username" /></td>
	</tr>
	<tr>
		<td>Password:</td>
		<td><input type="password" name="j_password"/ ></td>
	</tr>
	<tr>
		<td colspan="2"><input type="submit" value="Go" /></td>
	</tr>
</table>
</form>

The login-failed.html file displays a simple message if the Form authentication fails.

login-failed.html

<p>
Sorry, login failed!
</p>

The TestServlet class is shown below. It enumerates over the request headers from the browser and writes them to the response.

TestServlet.java

package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("This is the Test Servlet");

		Enumeration headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = (String) headerNames.nextElement();
			out.print("<br/>Header Name: <em>" + headerName);
			String headerValue = request.getHeader(headerName);
			out.print("</em>, Header Value: <em>" + headerValue);
			out.println("</em>");
		}
	}

}

In another tutorial, I changed the Tomcat HTTPS connector port to 4321 rather than the default 8443. I also changed the HTTP connector port's redirectPort to 4321 so that the request to 8080 will get redirected to port 4321 (to handle the transport-guarantee CONFIDENTIAL setting mentioned earlier).

    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="4321" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />
               
    <Connector port="4321" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />

(Continued on page 2)

Page:    1 2 3 >