On Tue, 13 Nov 2001 04:28, you wrote: > I need to make an Apache module (not a Registry script) which will: > > 1. Check for a cookie, and if not there, pushhandler to a module for > logging in (keeping the original request at hand for use after they > succeed in logging in). > 2. Extract data from the cookie (encrypted for security?) > 3. Based on data from both the query string ($r->args?) and from data in > the cookie, pushhandler to another module. > > I have looked at Apache::AuthCookie - it didn't seem to make much sense > to me. Apache::Session looks promising, but the instructions don't say > how to set up the mysql tables, etc. My worst problem is that I haven't > had occasion to deal with cookies much (setting, checking,etc.) in the > past and I know this is hampering my understanding.
You should definately be using Auth::Cookie for this. I would give the docs another read. It took me a couple of tries to get it working successfully, but I have implemented it in about 4 or 5 applications, and it works flawlessly. With Auth::Cookie it will handle the cookies for you, it will do the redirection to your login page for you, and it can handle logouts as well (by expiring the cookie). As for Apache::Session, it is really just a keyed data store with expiry times. You give it some data, and it gives you a key. If you come back later and give it the same key, it gives you back your data. A lot of people use Auth::Cookie and Apache::Session together to build a session management system, but I prefer just using a ticket based system with Auth::Cookie alone (See the Eagle book on how to do ticket based authentication). I have included a sample Auth::Cookie implementation that might give you some ideas. It is not complete, but it might get you going (I have stripped out some of the irrelevant code, so it probably won't work out of the box). Also you will have to provide your own login.pl and logout.pl scripts (I would use the examples that come with Auth::Cookie until you get a working system, then you can look at building your own. > In conclusion: I'm making a system/site where no .html files even exist. > I need to handle security via a mysql db, and to push handlers based on > a part of the url and a piece of the cookie which identifies the user as > either a teacher, student, or parent (oops... I gave it away ;-) After Auth::Cookie has finished it's phase, it will set the REMOTE_USER environment variable to the user that logged in. You could just as easily set this to 'teacher' or whatever. Then your content handler can look at this variable and decide what to do. HTH Cees package My::Auth::AuthCookie; require 5.000; use strict; use Apache::AuthCookie; use My::Crypt; @My::Auth::AuthCookie::ISA = qw(Apache::AuthCookie); # ################################################################################################################## # There are far more secure ways of handling the passphrase then keeping it in # the actual code, but this is by far the easiest... sub SECRET () { 'No one will ever guess this passphrase :)'; } my $CRYPTER ||= new My::Crypt; # This utility just uses the Crypt::CBC and # Storable modules to encrypt and decrypt perl # data structures. It also does an MD5 checksum sub authen_cred ($$\@) { my $self = shift; my $r = shift; my @creds = @_; # # get the entered details # my $email = $creds[0]; my $password = $creds[1]; # # ensure that the user is valid and authorized... # right now it accepts any email and password combo, # so obviously you would check this in a database or # something # if ($email && $password) { return $self->makeTicket($r, $email); } else { return; } } sub authen_ses_key ($$$) { my $self = shift; my $r = shift; my $ticket = shift; # # verify the ticket (to make sure no-one has tampered with it and it hasn't expired etc...) # my ($result, $message) = $self->verifyTicket($r, $ticket); # # Check the result and act appropriately... # if (!$result) { # $r->log->error("Browser returned bad cookie ($message)"); return undef; } else { # # Make and set a new cookie (so that the 'time' in the cookie is updated and expires # works as expected - since last access etc...) # my $new_ticket = $self->makeTicket($r, $message); $self->send_cookie($new_ticket); # # Return the 'message/string' which will be set in the environment # under REMOTE_USER (aka.. $ENV{REMOTE_USER}). In our case that is # the users email address which we pulled out of the ticket # return $message; } } #################################### # # makeTicket # # Generate a cookie/session_id/ticket for a user that has just logged in # borrowed from the Eagle book (by Lincoln Stein & Doug MacEachern) sub makeTicket { my $self = shift; my $r = shift; my $email = shift; my $ip = $r->connection->remote_ip; my $expires = 30; # The allowed amount of inactivity in minutes my $time = time; my $ticket = { time => $time, expires => $expires, email => $email, ip => $ip, }; # # return an encrypted version of the ticket # return $CRYPTER->encrypt($ticket); } #################################### # # verifyTicket # # Verify that the (already logged in user's) cookie/session_id/ticket is valid # # Errors # If there were any errors in verification then one of the following errors will # be set and can be used in the template: # # * ticket_invalid - The ticket could not be decrypted - might have been fiddled with by user? or maybe the # 'secret' on our side has changed? # * ticket_expired - The ticket has expired (aka - the session has expired!) # * ticket_invalid_ip - The connection was made form a different IP to the one that the cookie was intially sent to # sub verifyTicket { my $self = shift; my $r = shift; my $user_ticket = shift; my $ticket = {}; # # decrypt the ticket # $ticket = eval { $CRYPTER->decrypt($user_ticket); }; # # ensure the ticket is valid # if ($@) { $r->subprocess_env(MyAuthCookieReason => 'ticket_invalid'); return (0, 'invalid ticket'); } elsif ((time - $ticket->{time}) > $ticket->{expires}) { $r->subprocess_env(MyAuthCookieReason => 'ticket_expired'); return (0, 'ticket has expired'); } elsif (! $ticket->{ip} eq $r->connection->remote_ip) { $r->subprocess_env(MyAuthCookieReason => 'ticket_invalid_ip'); return (0, 'ticket has different ip'); } return (1, $ticket->{email}); } 1;