Using Valves to Intercept User Requests

A Web server wouldn’t be a Web server if it didn’t allow you to intercept user requests, examine them, and log them. As mentioned in Figure 7-1 shows a set of valves in a Tomcat installation.

image from book
Figure 7-1: Valves intercept requests for certain resources, and you can use them in conjunction with each other.

As Figure 7-1 shows, a valve configured at the engine level will intercept all requests to contexts on this engine, no matter what host or context they’re bound for. The valve at the host level intercepts all requests to this virtual host, and the valves in the contexts intercept only requests that are specifically for them. This means valves can be chained together to work in conjunction with each other.

Valves offer value-added functionality that includes the following:

  • Access logging

  • Single sign-on for all Web applications running on the server

  • Requests filtering/blocking by IP address and hostname

  • Detailed request dumps for debugging

Standard Valves

Valves are nested components in the Tomcat configuration hierarchy that can be placed inside <Engine>, <Host>, or <Context> containers. (Refer to Table 7-1 describes these standard valves.

Table 7-1: Standard Valves As Supplied by Tomcat

Valve Name

Description

Access log valve

Logs requests.

Single sign-on valve

Lets you pass user login information to other Web applications on the server. This means the users need to log in only once, no matter how many Web applications they visit.

Request filter valves

Enables selective filtering of incoming requests based on IP addresses or hostnames.

Request dumper valve

Prints the headers and cookies of incoming requests and outgoing responses to a log.

Using Access Log Valves

Logging access to resources is a common activity for Web server administrators. As such, Tomcat comes with a valve for logging access to resources, be that at the engine level, the host level, or the context level. The location of a log valve is fairly important from a performance point of view, because each log entry requires Tomcat to write data to disk. If you have a logging valve at the engine level of a busy server, as well as logging valves for every context, the log will be written to many times and will grow very large. However, you may need to do this to monitor each individual context as well as the whole server. This just illustrates the need for careful planning when using valves.

An access log valve isn’t a logger because a logger prints information and errors to a log file so that you can diagnose errors in Web applications. For example, if a component encounters problems and a user reports the error message to you, you’d look in the logger’s log because this is where the error will be reported. However, if you wanted to see how often a client at a certain IP address requests a certain resource, you’d examine the access log valve’s log file.

The logger’s format also depends on the application in question. If it has been written properly, all errors will be written to the error log file in a standard way so that they can be investigated and rectified. If not, you may see nasty Java stacktraces with details of the error buried among it.

The typical format for an access log valve is the common log file format, which you can find at http://www.w3.org/Daemon/User/Config/Logging.html#common-logfile-format. You may already have an analysis tool that can analyze log files in this format. If not, don’t worry— they’re quite common. AWStats (http://awstats.sourceforge.net) is a great open-source option, though you’ll need Perl to use it. Another option is Webalizer (http://www.mrunix.net/webalizer/).

Table 7-2 shows the attributes for the standard access log valve that’s supplied with Tomcat. In this case, the className attribute must be org.apache.catalina.valves.AccessLogValve.

Table 7-2: The Attributes for the Standard Access Log Valve

Attribute

Description

Required?

className

The Java class of the valve. This must be org.apache.catalina.valves.AccessLogValve.

Yes

condition

Turns conditional logging on. If set, the access log valve logs requests only if ServletRequest.getAttribute() is null. For example, if this value is set to userId, then a particular request will be logged only if ServletRequest.getAttribute("userId") == null.

No

directory

The directory where the log files will be placed. Usually relative to the CATALINA_HOME, but you can also specify an absolute path instead. The default is logs.

No

fileDateFormat

Allows a customized date format in the access log filename. The date format also decides how often the file is rotated. If you want to rotate every hour, then set this value to yyyy-MM-dd.HH.

No

pattern

Specifies the format used in the log. You can customize the format, or you can use common or combined as the format (the common format plus the referrer and user-agent are logged). To customize the format, you can use any of the following patterns interspersed with a literal string:

%a: Inserts remote IP address.

%A: Inserts local IP address (of URL resource).

%b: Inserts bytes sent count, excluding HTTP headers, shows - if zero.

%B: Inserts bytes sent count, excluding HTTP headers.

%D: Time taken to process the request, in milliseconds.

%h: Inserts remote hostname (or IP address if the resolveHosts attribute is set to false).

%H: Inserts the request protocol (HTTP).

%l: Inserts remote logical user name (always '-').

%m: Inserts request method such as GET and POST.

%p: Inserts the local TCP port where this request is received.

%q: Inserts the query string of this request.

%r: Inserts the first line of the request.

%s: Inserts the HTTP status code of the response.

%S: Inserts the user session ID.

%t: Inserts the date and time in common log file format.

%T: Time taken to process the request, in seconds.

%u: Inserts the remote user that has been authenticated (otherwise it’s -).

%U: Inserts the URL path of the request.

%v: Inserts the name of the local virtual host from the request.

%{xxx}i: Use this for incoming headers, where xxx is the header.

%{xxx}c: Use this for a specific cookie, where xxx is the name of the cookie.

%{xxx}r: Use this for ServletRequest attributes, where xxx is the attribute.

%{xxx}s: Use this for HttpSession attributes, where xxx is the attribute.

The default is common, which is %h %l %u %t "%r" %s %b.

No

prefix

The prefix added to the name of the log file.

No

resolveHosts

Determines if the log will contain hostnames via a reverse DNS lookup. This can take significant time if enabled. The default is false.

No

rotatable

Determines if log rotation should occur. If false, then this file is never rotated and the fileDateFormat attribute is ignored. Use this attribute with caution because the log file could grow very large indeed. The default is true.

No

suffix

The extension added to the name of the log file.

No

Examining an Example Access Log Valve

This section contains an example access log valve to demonstrate the attributes listed in Table 7-2. By default, the access log valves in server.xml are commented out to disable them. This does, however, make it easy to activate them. Open server.xml, and navigate to the localhost <Host> entry. The access log valve is configured after the large comment section (see Listing 7-1).

Listing 7-1: The Access Log Valve in server.xml

image from book
 <Valve className="org.apache.catalina.valves.AccessLogValve"         directory="logs"         prefix="localhost_access_log."         suffix=".txt"         pattern="common"         resolveHosts="false"/> 
image from book

You may not have this entry if you’ve previously used the admin Web interface. As noted in Chapter 6, the admin application rewrites a new server.xml once you’ve made any configuration changes. This means that comments are lost, even if they contain useful default components. The good news is that the old server.xml should have been saved under another name in the conf directory, so you can copy and paste the valve entry from there into the new server.xml.

Uncomment this entry, start/restart Tomcat, and point your browser to http://localhost:8080. You should see the default Tomcat welcome page. Now examine the CATALINA_HOME/logs directory, and open the localhost_access_log.DATE.txt file. You’ll see the access log entry for the Web page itself, though you’ll also see the entries for the associated image files, all in the common log file format, as shown in Listing 7-2.

Listing 7-2: The localhost_access_log.DATE.txt Log File

image from book
 127.0.0.1 - - [01/Aug/2004:20:47:54 +0000]  "GET / HTTP/1.1" 200 9312  127.0.0.1 - - [01/Aug/2004:20:47:54 +0000]  "GET /tomcat.gif HTTP/1.1" 200 1934  127.0.0.1 - - [01/Aug/2004:20:47:54 +0000]  "GET /jakarta-banner.gif HTTP/1.1" 200 8584  127.0.0.1 - - [01/Aug/2004:20:47:54 +0000]  "GET /tomcat-power.gif HTTP/1.1" 200 2324 
image from book

You may want to experiment further with other attributes of the standard access log valve by modifying the previous <Valve> entry. You should experiment with other access log valve configurations, such as valves at the context level, which you configure in the appropriate context XML file, and valves at the engine level. This way you can use tools to analyze access at various levels of the server.

Using Request Filter Valves

As a server administrator you’ll often find it useful to restrict access to certain resources. You’ve already seen password protection for administration resources, but Tomcat also allows you to use request filter valves to block access so that a user doesn’t even get as far as the password prompt. You can use this facility to block access to admin resources except for users who are on the local machine or an admin-only machine. Other options can include blocking denial-of-service (DoS) attacks or denying access to sales data for nonsales personnel, and so on.

Two types of request filter valves exist: the remote address valve and the remote host valve. The first of these filters requests by the client’s IP address, and the second filters by the client’s host. Table 7-3 shows the attributes of the remote address valve.

Table 7-3: The Attributes of the Remote Address Request Filter Valve

Attribute

Description

Required?

allow

A comma-separated list of regular expressions used to match the client’s IP address. If there’s a match, then the request is allowed through to its destination. If not, it’s blocked. If this attribute isn’t specified, then all requests are allowed except if they match a pattern in the deny attribute.

No

className

The Java class of the valve. This must be org.apache.catalina.valves.RemoteAddrValve.

Yes

deny

A comma-separated list of regular expressions used to match the client’s IP address. If there’s a match, then the request is blocked. If not, it’s allowed.

No

It’s now possible to see how you can allow access only to those users on a local or admin machine. In this example, you’d add the IP address of the local (or admin) machine to the allow list. Listing 7-3 shows the scenario where both conditions are allowed (assuming the admin machine has 192.168.0.73 as its IP address).

Listing 7-3: An Example Remote Address Request Filter Valve

image from book
 <Valve className="org.apache.catalina.valves.RemoteAddrValve"         allow="127.0.0.1,192.168.0.73"/> 
image from book

Visit a page on the local Tomcat server. You should see the page as usual. Now remove the 127.0.0.1 portion, and restart Tomcat. Visit the same page, and you should be blocked, as shown in Figure 7-2.

image from book
Figure 7-2: A blocked URL using the remote address request filter valve

Note 

If a blank page isn’t a satisfactory way to indicate a blocked page, you should use servlet filters. These are part of a Web application and can be used to show custom error pages. If you’re interested in using a filter for this task, one is provided on the Apress Web site that replicates the behavior described in this section.

You can also achieve this effect by denying access to the localhost:

 <Valve className="org.apache.catalina.valves.RemoteAddrValve"         deny="127.0.0.1"/> 

Filtering by client host is just as easy. The only differences between the two are the class that implements the valve and the values of the regular expressions. In the case of the remote host request filter valve, the class is org.apache.catalina.valves.RemoteHostValve, and the regular expressions are hostnames instead of IP addresses.

 <Valve className="org.apache.catalina.valves.RemoteHostValve"         allow="*.com"/> 

Note 

The remote host request filter requires a reverse DNS lookup, so the server must have access to DNS.

Request Dumper Valve

The request dumper valve allows you to debug Web applications by dumping the headers and cookies of requests and responses to a log. The request dumper valve uses whichever logging mechanism you’ve configured for the component that contains the valve, be that a <Logger> in Tomcat 5.0.x or Log4J in Tomcat 5.5 (see Chapter 4 for more information on logging).

You can use it for the following:

  • Checking how the scope of a valve affects the requests that are processed

  • Debugging other valves and any other request-processing components that are configured on the server

To configure a request dumper valve, modify server.xml and add the following to the context, virtual host, or engine that you want to examine:

 <Valve className="org.apache.catalina.valves.RequestDumperValve"/> 

If you add the request dumper valve to the default server.xml at the engine level, it will use the logger shown in Listing 7-4.

Listing 7-4: An Engine-Level Logger

image from book
 <!-- Global logger unless overridden at lower levels -->  <Logger className="org.apache.catalina.logger.FileLogger"          prefix="catalina_log." suffix=".txt"          timestamp="true"/> 
image from book

For Tomcat 5.0.x, if you configure it at the host level (for the localhost host) or the context level for the default Tomcat distribution, it will use the logger shown in Listing 7-5, unless you configure a new logger for the context.

Listing 7-5: A Host-Level Logger

image from book
 <Logger className="org.apache.catalina.logger.FileLogger"          directory="logs"  prefix="localhost_log." suffix=".txt"          timestamp="true"/> 
image from book

For Tomcat 5.5 you’d use the following logger for logging at the host level. Each line of the log has INFO priority.

 log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost] 

If you wanted logging at the context level, assuming that your context is called tomcatBook, you’d use the following:

 log4j.logger.org.apache.catalina.core.ContainerBase.  [Catalina].[localhost].[/tomcatBook] 

This means the request dumper valve inherits the logger from a higher-level component, which isn’t always desirable if you’re troubleshooting a specific Web application’s request/ response-processing pipeline.

Once you’ve set up the valve, visit a Web application that will be covered by the valve. Once your request has been processed, open the appropriate log file. You should see something similar to Listing 7-6. The version of Tomcat and the settings of your logger will affect this, though the messages will be the same.

Listing 7-6: The Output of the Request Dumper Valve

image from book
 REQUEST URI=/tomcatBook/  authType=null  characterEncoding=null  contentLength=-1  contentType=null  contextPath=/tomcatBook  cookie=JSESSIONID=7F31F129712D208903FC6F50FD5143EA  header=host=localhost:8080  header=user-agent=Mozilla/5.0  (Windows; U; Windows NT 5.0; rv:1.7.3) Gecko/20040913 Firefox/0.10.1  header=accept=text/xml,application/xml,application/xhtml+xml,  text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5  header=accept-language=en-us,en;q=0.5  header=accept-encoding=gzip,deflate  header=accept-charset=ISO-8859-1,utf-8;q=0.7,*;q=0.7  header=keep-alive=300  header=connection=keep-alive  header=cookie=JSESSIONID=7F31F129712D208903FC6F50FD5143EA  locale=en_US  method=GET  pathInfo=null  protocol=HTTP/1.1  queryString=null  remoteAddr=127.0.0.1  remoteHost=127.0.0.1  remoteUser=null  requestedSessionId=7F31F129712D208903FC6F50FD5143EA  scheme=http  serverName=localhost  serverPort=8080  servletPath=/index.jsp  isSecure=false  --------------------------------------------------------------- --------------------------------------------------------------- authType=null  contentLength=-1  contentType=text/html;charset=ISO-8859-1  message=null  remoteUser=null  status=200  =============================================================== 
image from book

As you can see, this contains a fair amount of information, all of which can be used to analyze a client’s interaction with your server. A word of warning, though: this valve decodes any parameters sent with the request using the platform’s default encoding. This may affect Web applications on the server because calls to request.setCharacterEncoding() will have no effect.

Using Single Sign-on Valves

Another standard valve that’s frequently used is the single sign-on valve. Conventionally, whenever users of a Web application reaches a protected page, they will be required to log in, a process that’s repeated if they browse to another Web application on the same server. Using single sign-on, it’s possible to eliminate this repetition, provided that all the Web applications on a host use the same Tomcat realm.

The single sign-on valve caches the user’s credentials on the server and will authenticate users as they move between Web applications on a host. The credentials are cached in the client’s session, which means that a single sign-on will be effective throughout a session. The user’s browser will send a cookie with a value that uniquely identifies this user as a user who has signed in. The valve then associates the new request with the existing user credentials and allows the user to visit protected resources. This is one of the main reasons for having a common realm for the host.

Table 7-4 describes the attributes of the single sign-on valve.

Table 7-4: The Attributes of the Single Sign-on Valve

Attribute

Description

Required?

className

The Java class of the valve. This must be org.apache.catalina.authenticator.SingleSignOn.

Yes

debug

Tomcat 5.0.x only. Level of debugging. The default is zero (no debugging).

No

requireReauthentication

Determines whether the valve should use the authentication realm to authenticate the user every time authentication is required. If false, the valve uses the cookie sent by the client and automatically authenticates the user without rechecking the realm. The default is false.

No

Configuring a Single Sign-on Valve

Before seeing what single sign-on does, you should first experience the problem that sometimes makes it necessary to configure single sign-on. You’ll need two separate Web applications that are both protected. Luckily Tomcat comes with two such Web applications: the manager application and the admin application. If you’re using Tomcat 5.5 you’ll have to download the admin application or protect another application for this example to work.

You should already have a user who has the manager role required for access to the manager application and a user who has the admin role required for access to the admin application. You may even have a user who has both. If not, then you must create one in tomcat-users.xml now, as shown in Listing 7-7.

Listing 7-7: A User with Manager and Admin Roles Defined in tomcat-users.xml

image from book
 <role rolename="manager"/>  <role rolename="admin"/>  <user username="tomcat" password="tomcat" roles="tomcat,manager,admin"/> 
image from book

Here the tomcat user has three roles: tomcat, manager, and admin. Now start/restart Tomcat, and navigate to http://localhost:8080/manager/html/. You’ll be asked for your user details as usual. Now sign in as the user with both roles. Once you’ve done so, you should see the Web interface of the manager application.

The next step is to navigate to http://localhost:8080/admin/. You’ll be presented with the form for logging into the admin application, which means your login for the manager application hasn’t carried over into the admin application despite the details being valid for both. This is where single sign-on comes in.

Open server.xml, and navigate to the valve as shown in Listing 7-8. It’s the first valve in the localhost host, after the large commented-out section.

Listing 7-8: The Single Sign-on Valve in server.xml

image from book
 <!-- Normally, users must authenticate themselves to each Web app       individually. Uncomment the following entry if you would like       a user to be authenticated the first time they encounter a       resource protected by a security constraint, and then have that       user identity maintained across *all* Web applications contained       in this virtual host. -->  <!-- <Valve className="org.apache.catalina.authenticator.SingleSignOn"             debug="0"/>  --> 
image from book

Uncomment the valve, and restart Tomcat. Make sure you’ve closed your browser windows to start a new session, and navigate to http://localhost:8080/manager/html/ as before. Log in as the user with both roles as before. Once you’ve logged in successfully, navigate to http://localhost:8080/admin/. This time you won’t be asked to log in again because the valve will have recognized you from the cookie sent by your browser and will have authenticated you.



Pro Jakarta Tomcat 5
Pro Apache Tomcat 5/5.5 (Experts Voice in Java)
ISBN: 1590593316
EAN: 2147483647
Year: 2004
Pages: 94

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net