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 6 - Authentication and Authorization
Authorization Handlers

In this section...

A Gender-Based Authorization Module
Advanced Gender-Based Authorization
Authorizing Against a Database
Authentication and Authorization's Relationship with Subrequests
Binding Authentication to Authorization


   Show Contents   Go to Top   Previous Page   Next Page

Sometimes it's sufficient to know that a user can prove his or her identity, but more often that's just the beginning of the story. After authentication comes the optional authorization phase of the transaction, in which your handler gets a chance to determine whether this user can fetch that URI.

If you felt constrained by HTTP's obsession with conventional password checking, you can now breathe a sigh of relief. Authorization schemes, as opposed to authentication, form no part of the HTTP standard. You are free to implement any scheme you can dream up. In practice, most authentication schemes are based on the user's account name, since this is the piece of information that you've just gone to some effort to confirm. What you do with that datum, however, is entirely up to you. You may look up the user in a database to determine his or her access privileges, or you may grant or deny access based on the name itself. We'll show a useful example of this in the next section.

A Gender-Based Authorization Module

   Show Contents   Go to Top   Previous Page   Next Page

Remember the bar that lets only women through the door on Ladies' Night? Here's a little module that enforces that restriction. Apache::AuthzGender enforces gender-based restrictions using Jon Orwant's Text::GenderFromName, a port of an awk script originally published by Scott Pakin in the December 1991 issue of Computer Language Monthly. Text::GenderFromName uses a set of pattern-matching rules to guess people's genders from their first names, returning "m", "f", or undef for male names, female names, and names that it can't guess.

Example 6-9 gives the code and a configuration file section to go with it. In order to have a username to operate on, authentication has to be active. This means there must be AuthName and AuthType directives, as well as a require statement. You can use any authentication method you choose, including the standard text, DBM, and DB modules. In this case, we use Apache::AuthAny from the example earlier in this chapter because it provides a way of passing in arbitrary usernames.

In addition to the standard directives, Apache::AuthzGender accepts a configuration variable named Gender. Gender can be either of the characters M or F, to allow access by people of the male and female persuasions, respectively.

Turning to the code (Example 6-9), the handler() subroutine begins by retrieving the username by calling the connection object's user() method. We know this value is defined because it was set during authentication. Next we recover the value of the Gender configuration variable.

We now apply the Text::GenderFromName module's gender() function to the username and compare the result to the desired value. There are a couple of details to worry about. First, gender() is case-sensitive. Unless presented with a name that begins with an initial capital, it doesn't work right. Second, the original awk script defaulted to male when it hadn't a clue, but Jon removed this default in order to "contribute to the destruction of the oppressive Patriarchy." A brief test convinced us that the module misses male names far more often than female ones, so the original male default was restored (during our test, the module recognized neither of the author's first names as male!). A few lines are devoted to normalizing the capitalization of usernames, changing the default gender to male, and to uppercasing gender()'s return value so that it can be compared to the Gender configuration variable.

If there's a mismatch, authorization has failed. We indicate this in exactly the way we do in authorization modules, by calling the request object's note_basic_auth_failure() method, writing a line to the log, and returning a status code of AUTH_REQUIRED. If the test succeeds, we return OK.

Example 6-9. Apache::AuthzGender Implements Gender-Based Authorization

package Apache::AuthzGender;
use strict;
use Text::GenderFromName qw(gender);
use Apache::Constants qw(:common);
sub handler {
   my $r = shift;
    my $user = ucfirst lc $r->connection->user;
    my $gender = uc($r->dir_config('Gender')) || 'F';
    my $guessed_gender = uc(gender($user)) || 'M';
    unless ($guessed_gender eq $gender) {
      $r->log_reason("$user is of wrong apparent gender", $r->filename); 
    return OK;

Example access.conf:

<Location /ladies_only>
 AuthName Restricted
 AuthType Basic
 PerlAuthenHandler Apache::AuthAny
 PerlAuthzHandler  Apache::AuthzGender
 PerlSetVar Gender F
 require valid-user
   Show Contents   Go to Top   Previous Page   Next Page
Copyright 1999 by O'Reilly & Associates, Inc.