Baking with Julia
October 23, 2000
Since we successfully "logged in" the user, by virtue of pulling
their user_info record, we can proceed with creating session cookies. We
know that we'll succeed in pulling their preferences record, because we've
established that all user accounts have a user_prefs record, created by
a script invoked when building a new user's account (something we'll see in a
future installment).
A cookie, as we explained last month, is a chunk of arbitrary data. This data
is tagged such that it can only be "seen" (delivered to, really) by
the host or domain that issued the cookie. Cookies can be set to expire at a
given date and time, or in the absence of such, will expire when the browser is
closed. Cookies are not unlimited ("there's no free lunch",
"it's not a buffet", take your pick), and browsers may limit the size
and number of cookies that can be issued from a server. To be safe, you
probably don't want to issue more than a handful of cookies, and keep them
under 4K in length. Cookies aren't meant for storing large quantities of data -
- if you have such a need, store the data in the backend database, and a record
number or other identifier in the cookie.
We're going to issue two cookies: one called 'site-auth' which will act as an
"authentication token". By this, we mean that this cookie and the data it
contains is the key with which this user can access account-specific pages or
services on our site. The presence of this cookie is what we mean when we say
that a user is "logged in" to our web site. The absence, expiration, or
deletion of this cookie will immediately render the user "logged out". It's
important that the user not be able to modify the authentication token, such
that they can masquerade as a different registered user. Just how important
this is depends on the nature of your site, and level of encryption you wish to
invoke.
In our case, we'll use a checksum to preserve the integrity of the 'site-
auth' token. Continuing from the script we saw earlier, let's add a
subroutine to bake the authentication token cookie.
use Digest::HMAC_MD5;
sub bake_auth_cookie {
my ($userid,$username)=@_;
my $cgiobj=new CGI;
#userid, username, and an MD5 checksum
my $hmac = Digest::HMAC_MD5->new("digest#1pass");
$hmac->add($userid.$username);
my $cookie=
$cgiobj->cookie(
-name=>'site-auth',
-value=>$userid."\t".$username."\t".$hmac->b64digest,
#-expires=>'+6M',# not used for session-only cookie
-path=>'/'
);
return $cookie;
}
When called, we'll pass the $userid and $username parameters to
&bake_auth_cookie. This subroutine uses a special Perl module called
Digest::HMAC_MD5 -- you may need to install this module
if Perl complains that it's not already installed on your system. We're using
the MD5 module to calculate a keyed checksum.
Specifically, we invoke Digest::HMAC_MD5 to create a digest object keyed to a
specific password -- in this fictional example, "digest#1pass", but
you should select some other secure password. Once this digest object is
created, we add to it a string -- in this case, the concatenation of the
$userid and $username variables. The result is a checksum unique
to this user's id and name, further keyed to the password we provided. Later,
when we read back the cookie, we can determine whether the checksum matches the
id and name values contained in that cookie. If not, someone may have tampered
with one of those values in an attempt to masquerade as a different user. We
can then deny further access to the page that they attempted to view.
We can now create a cookie object using the data collected: the user's id,
name, and checksum. These values are strung together delimited by tab
characters, in the parameter -value of the CGI module cookie() call.
Note that we output the checksum as text characters by virtue of the
b64digest() method. The -expires parameter has been commented
out, resulting in a session-only cookie.
If you wanted the user's authentication token to hang around after the browser
is closed, so that they can re-enter the web site next time without manually
logging in, simply set an expiration value. We've included an example of
"6 months hence" in the commented out code above. This is a technique
typically used on sites which offer you the option "remember my login next
time I visit", for example.
While we're talking about this cookie, writing another subroutine to expire
this cookie -- that is, log the user out, is simple. Simply create a cookie
object containing only the same name (site-auth) and an -expires
value of 0. When the cookie is output (which we haven't done yet), it will
expire immediately, thereby removing the authentication token from the user's
machine.
The Personalization Database
The Perl You Need to Know
Fresh Out of the Oven
|