How do I use Basic authentication and SSL with Tomcat?
Author: Deron Eriksson
Description: This tutorial describes the setup of Basic authentication and SSL 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 >

In another tutorial, we set up TomcatSW to use SSL with a self-signed certificate. We did this by running the 'keytool' utility that comes with the JDKW. That generated a '.keystore' certificate file in our home directory. After that, we uncommented the SSL HTTP Connector element in Tomcat's server.xml file. If this sounds confusing, please refer to the tutorial where I described setting up SSL on Tomcat.

In yet another tutorial, we set up a web application to use Basic authentication with Tomcat. As a result, I won't go into the details related to setting up Basic authentication. Rather, I'll show you how you can modify that demo project to do authentication via SSL so that your user name and password are encrypted as they pass over the network.

The project has the same structure as the Basic authentication tutorial.

Eclipse Navigator View

The TestServlet class is identical, so I won't describe it.

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;

import org.apache.tomcat.util.buf.Base64;

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>");
		}

		out.println("<hr/>");
		String authHeader = request.getHeader("authorization");
		String encodedValue = authHeader.split(" ")[1];
		out.println("Base64-encoded Authorization Value: <em>" + encodedValue);
		String decodedValue = Base64.base64Decode(encodedValue);
		out.println("</em><br/>Base64-decoded Authorization Value: <em>" + decodedValue);
		out.println("</em>");
	}

}

The web.xmlW file is nearly identical except that the security-constraint → user-data-constraint → transport-guarantee has been changed from NONE to CONFIDENTIAL. This means that the user name and password data must travel over HTTP securely (ie, HTTPS), so if an HTTP request is made for a protected resource, the request will be redirected to the HTTPS connection for authentication.

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>BASIC</auth-method>
	</login-config>

</web-app>

To help show how this redirection from HTTP to HTTPS works, I changed the default Tomcat HTTPS connector port number from 8443 to 4321. Notice that I also changed the 'redirectPort' attribute in the regular HTTP connector to also be 4321. What this means is that if a request is made over HTTP for a protected resource that requires authentication, the request will be forwarded to the HTTPS connector on port 4321.

    <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 >