Top Ten Tomcat Configuration Tips
Pages: 1, 2
6. Configuring Single Sign-On
Once you've set up your realm and method of authentication, you'll need to deal with the actual process of logging the user in. More often than not, logging into an application is a nuisance to an end user, and you will need to minimize the number of times they must authenticate. By default, each web application will ask the user to log in the first time the user requests a protected resource. This can seem like a hassle to your users if you run multiple web applications and each application asks the user to authenticate. Users cannot tell how many separate applications make up any single web site, so they won't know when they're making a request that crosses a context boundary, and will wonder why they're being repeatedly asked to log in.
The "single sign-on" feature of Tomcat 4 allows a user to
authenticate only once to access all of the web applications
loaded under a virtual host. To use this feature, you need only
Valve element at the host level. This looks
like the following:
<Valve className="org.apache.catalina.authenticator.SingleSignOn" debug="0"/>
The Tomcat distribution's default server.xml contains a
commented-out single sign-on
Valve configuration example that
you can uncomment and use. Then, any user who is considered
valid in a context within the configured virtual host will be
considered valid in all other contexts for that same host.
There are several important restrictions for using the single sign-on valve:
The valve must be configured and nested within the same
Hostelement that the web applications (represented by
Contextelements) are nested within.
Realmthat contains the shared user information must be configured either at the level of the same
Hostor in an outer nesting.
Realmcannot be overridden at the
The web applications that use single sign-on must use one of Tomcat's built-in authenticators (in the
<auth-method>element of web.xml), rather than a custom authenticator. The built-in methods are
If you're using single sign-on and wish to integrate another third-party web application into your web site, and the new web application uses only its own authentication code that doesn't use container-managed security, you're basically stuck. Your users will have to log in once for all of the web applications that use single sign-on, and then once again if they make a request to the new third-party web application. Of course, if you get the source and you're a developer, you could fix it, but that's probably not so easy to do.
The single sign-on valve requires the use of HTTP cookies.
7. Configuring Customized User Directories
Some sites like to allow individual users to publish a directory of web pages on the server. For example, a university department might want to give each student a public area, or an ISP might make some web space available on one of its servers to customers that don't have a virtually hosted web server. In such cases, it is typical to use the tilde character (~) plus the user's name as the virtual path of that user's web site:
Tomcat gives you two ways to map this on a per-host basis,
using a couple of special
Listener elements. The
className attribute should be
org.apache.catalina.startup.UserConfig, with the
specifying one of several mapping classes. If your system runs
Unix, has a standard /etc/passwd file that is readable by the
account running Tomcat, and that file specifies users' home
directories, use the
PasswdUserDatabase mapping class:
<Listener className="org.apache.catalina.startup.UserConfig" directoryName="public_html" userClass="org.apache.catalina.startup.PasswdUserDatabase"/>
Web files would need to be in directories such as /home/users/ian/public_html or /users/jbrittain/public_html. Of course, you can change public_html to be whatever subdirectory into which your users put their personal web pages.
In fact, the directories don't have to be inside of a user's
home directory at all. If you don't have a password file but
want to map from a user name to a subdirectory of a common
parent directory such as /home, use the
<Listener className="org.apache.catalina.startup.UserConfig" directoryName="public_html" homeBase="/home" userClass="org.apache.catalina.startup.HomesUserDatabase"/>
In this case, web files would be in directories such as /home/ian/public_html or /home/jasonb/public_html. This format is more useful on Windows, where you'd likely use a directory such as C:\home.
Listener elements, if present, must be inside of a
element, but not inside of a
Context element, as they apply to the
8. Using CGI Scripts with Tomcat
Tomcat is primarily meant to be a servlet/JSP container, but
it has many capabilities rivalling a traditional web server. One
of these is support for the Common Gateway Interface (CGI),
which provides a means for running an external program in
response to a browser request, typically to process a web-based
form. CGI is called "common" because it can invoke programs in
almost any programming or scripting language: Perl, Python,
Unix shell scripting, and even Java are all supported
options. However, you probably wouldn't run a Java application as
a CGI due to the start-up overhead; elimination of this overhead
was what led to the original design of the servlet
specification. Servlets are almost always more efficient than
CGIs because you're not starting up a new operating-system-level
process every time somebody clicks on a link or button.
Tomcat includes an optional CGI servlet that allows you to run legacy CGI scripts; the assumption is that most new back-end processing will be done by user-defined servlets and JSPs.
To enable Tomcat's CGI servlet, you must do the following:
Rename the file servlets-cgi.renametojar (found in CATALINA_HOME/server/lib/) to servlets-cgi.jar, so that the servlet that processes CGI scripts will be on Tomcat's
In Tomcat's CATALINA_BASE/conf/web.xml file, uncomment the definition of the servlet named
cgi(this is around line 241 in the distribution).
Also in Tomcat's web.xml, uncomment the servlet mapping for the
cgiservlet (around line 299 in the distributed file). Remember, this specifies the HTML links to the CGI script.
Either place the CGI scripts under the WEB-INF/cgi directory (remember that WEB-INF is a safe place to hide things that you don't want the user to be able to view, for security reasons), or place them in some other directory within your context and adjust the
cgiPathPrefixinitialization parameter of the
CGIServletto identify the directory containing the files. This specifies the actual location of the CGI scripts, which typically will not be the same as the URL in the previous step.
Restart Tomcat, and your CGI processing should now be operational.
The default directory for the servlet to locate the actual scripts is WEB-INF/cgi. As has been noted, the WEB-INF directory is protected against casual snooping from browsers, so this is a good place to put CGI scripts, which may contain passwords or other sensitive information. For compatibility with other servers, though, you may prefer to keep the scripts in the traditional directory, /cgi-bin, but be aware that files in this directory may be viewable by the curious web surfer. Also, on Unix, be sure that the CGI script files are executable by the user under which you are running Tomcat.
9. Changing Tomcat's JSP Compiler
In Tomcat 4.1 (and above, presumably), compilation of JSPs
is performed by using the Ant program controller directly from
within Tomcat. This sounds a bit strange, but it's part of what
Ant was intended for; there is a documented API that lets
developers use Ant without starting up a new JVM. This is one
advantage of having Ant written in Java. Plus, it means you can
now use any compiler supported by the
javac task within Ant;
these are listed in the
javac page of the Apache Ant manual. It is
easy to use because you need only an
<init-param> with a
name of "compiler" and a value of one of the supported compiler
<servlet> <servlet-name>jsp</servlet-name> <servlet-class> org.apache.jasper.servlet.JspServlet </servlet-class> <init-param> <param-name>logVerbosityLevel</param-name> <param-value>WARNING</param-value> </init-param> <init-param> <param-name>compiler</param-name> <param-value>jikes</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet>
Of course, the given compiler must be installed on your
system, and the
CLASSPATH may need to be set, depending on which
compiler you choose.
10. Restricting Access to Specific Hosts
Sometimes you'll only want to restrict access to Tomcat's web app
to only specified host names or IP addresses. This way, only clients
at those specified sites will be served content. Tomcat comes with
Valves that you can configure and use for this purpose:
Valves allow you to filter requests by host name or by
IP address, and to allow or deny hosts that match, similar to
the per-directory Allow/Deny directives in Apache
httpd. If you
run the Admin application, you might want to only allow access to it
from localhost, as follows:
<Context path="/path/to/secret_files" ...> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1" deny=""/> </Context>
If no allow pattern is given, then patterns that match the
deny attribute patterns will be rejected, and all others will be
allowed. Similarly, if no deny pattern is given, patterns that
allow attribute will be allowed, and all others will
Jason Brittain is a Senior Software Engineer at Symantec Corporation's Network and Gateway Security Solutions Team, working on the AntiSpam product. He has contributed to many Apache Jakarta projects, and has been an active open source software developer for several years.
Ian F. Darwin has worked in the computer industry for three decades: with Unix since 1980, Java since 1995, and OpenBSD since 1998. He is the author of two O'Reilly books, Checking C Programs with lint and Java Cookbook, and co-author of Tomcat: The Definitive Guide with Jason Brittain.
O'Reilly & Associates recently released (June 2003) Tomcat: The Definitive Guide.
Sample Chapter 6, "Tomcat Security," is available free online.
For more information, or to order the book, click here.
Return to ONJava.com.