home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright © 1999 by O'Reilly & Associates, Inc.


 


   Show Contents   Previous Page   Next Page

Chapter 5 - Maintaining State
Other Server-Side Techniques

In this section...

Introduction
Non-DBI Databases
Using Authentication to Provide Session IDs
Apache::Session

Introduction

   Show Contents   Go to Top   Previous Page   Next Page

Before we finish up this chapter, we touch on a couple of other techniques for storing state information on the server side of the connection.

Non-DBI Databases

   Show Contents   Go to Top   Previous Page   Next Page

Because of its portability, the DBI database interface is probably the right choice for most server-side database applications. However, any database system that was designed to support multiple write access will work for this application. For example, the object-oriented ACEDB system that Lincoln works with is well suited to applications that require complex, richly interlinked information to be stored. The database is freeware; you can find out more about it at http://stein.cshl.org/AcePerl/.

You might be tempted to try to store session information using a Unix NDBM, GDBM, or DB_FILE database. If you try this, you may be in for an unpleasant surprise. These databases were designed for good multiuser read performance but not for transactions in which several processes are reading and writing simultaneously. They keep an in-memory cache of a portion of the database and don't immediately know when another process has updated a portion that's cached. As a result, the database can easily become corrupt if multiple Apache daemons open it for writing.

You can work around this problem by carefully locking the files, flushing after each write, and closing and reopening the file at strategic points, but believe us, it isn't worth it. Version 2 of the Berkeley DB library does support transactions, however, and Paul Marquess's experimental Berkeley_DB module provides an interface to it. We have not experimented with this database yet, but it looks like it might provide a lightweight solution for storing web session information in situations where a DBI database would be overkill.

Using Authentication to Provide Session IDs

   Show Contents   Go to Top   Previous Page   Next Page

Because the techniques for storing state information on the server side all require some sort of session ID to be maintained by the browser, they share a drawback. Regardless of whether the session ID is stored in a cookie or inside the URI, it sticks to the browser, not to the user. When the reigning hangman champ moves from his home computer to his office computer, he loses access to his current score information. Of course you could instruct users to write down their session IDs and type them back into the URI or cookie file when they move to a new machine, but this is awkward and inconvenient. You could try to recover session IDs from usernames, but this makes it too easy for people to steal each other's sessions.

In some applications, it makes sense to give each user a unique username/password pair and ask users to log in to your application. You can then use the username as the session key and be guaranteed that no sessions will conflict. Users can't steal each others' sessions without guessing the password, which is sufficient security for most applications.

The simplest way to do this is to use Apache's built-in authentication modules for password-protecting your script's URI. When the user tries to access the script, he is presented with a dialog box prompting him for his username and password. Apache verifies the information he provides against a file of stored usernames and passwords and allows access to the script if the information checks out. Before calling your script, Apache places the username into the request object. If you are using Apache::Registry, this information can be recovered from the CGI environment variable $ENV{REMOTE_USER}. From within an Apache Perl module, you can recover the username from the connection object in this way:

$username = $r->connection->user;

With this technique we can write a concise replacement for the get_session_id() subroutine in the server-side hangman scripts:

sub get_session_id {
  return $ENV{REMOTE_USER};
}

The Apache distribution comes with a variety of authentication modules that use text files or Unix DBM files as their password databases. These may be adequate for your needs, or you might want to integrate the database of usernames and passwords with the database you use to store session information. The next chapter shows you how to do this and much more.

Apache::Session

   Show Contents   Go to Top   Previous Page   Next Page

After this chapter was written, Jeffrey Baker released an Apache::Session module that implements many of the techniques described in this chapter. This module had undergone several revisions, including contributions from many mod_perl developers that have stabilized and enhanced Apache::Session, making it fit for a production environment across all platforms. We strongly recommend taking a look at this module when considering application state management implementation.

   Show Contents   Go to Top   Previous Page   Next Page
Copyright © 1999 by O'Reilly & Associates, Inc.