Show Contents Previous Page Next Page
Chapter 5 - Maintaining State / Storing State Information in SQL Databases URI-Based Session ID Problems and Solutions
There are a couple of problems with URI-based session IDs. One is that because the session ID is tacked onto the end of the URI, relative URIs will no longer work correctly. For example, a reference to another Apache::Registry script named high_scores.pl located in the same directory will be resolved by the browser to something like this:
http://your.site/perl/hangman.pl/high_scores.pl
This is obviously not what you want, because the session ID has been replaced by the name of the script you want to run! Fortunately, the Apache API provides a simple fix for this. Store the session ID to the left of the script name rather than the right, like this:
http://your.site/fd2c95dd/perl/hangman6.cgi
To handle URIs like this, you can write a custom URI translation handler to
modify the URI before it gets to the script. The full details of writing translation
handlers are discussed in Chapter 7, Other Request Phases, but a simple module to accomplish this named Apache::StripSession
is shown in Example 5-7. Briefly, the module
checks whether the requested URI begins with something that looks like a session
ID (eight hexadecimal digits). If it does, the handler strips out the session
ID and uses subprocess_env() to place the ID in an environment variable
named SESSION_ID . The handler replaces the request's original URI
with the altered one and then returns DECLINED , telling Apache
to pass the request onward to the standard translation handlers that will do
the work of turning the new URI into a physical file path.
Example 5-7. A Translation Handler
for Stripping Session IDs from URIs
package Apache::StripSession;
# file: Apache/StripSession.pm
use strict;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
my($junk, $session, @rest) = split '/', $r->uri;
return DECLINED unless $session =~ /^[0-9a-h]{8}$/; $r->subprocess_env('SESSION_ID' => $session);
my $new_uri = join "/", "", @rest;
$r->uri($new_uri);
return DECLINED;
}
1;
__END__
Add this directive to srm.conf to activate Apache::StripSession:
PerlTransHandler Apache::StripSession
With this translation handler in place, the get_session_id() no longer has to play games with the additional path information in order to recover the session ID. It can just read it from the environment. The other change to the subroutine is that the call to redirect() now places the session ID in front of the script name rather than after it:
sub get_session_id {
expire_old_sessions();
return check_id($ENV{SESSION_ID}) if $ENV{SESSION_ID};
my $session_id = generate_id();
die "Couldn't make a new session id" unless $session_id;
print redirect("/$session_id" . script_name());
exit 0;
}
A more serious potential problem with URI-based session IDs is that under some circumstances it is possible for the session ID to "leak" to other sites via the HTTP referrer header (which, for historical reasons, is spelled "Referer"). If a page that has a session ID in its URI contains a hypertext link to another site, or even an image whose source is at another site, the page's URI, session ID included, will show up in the remote site's referrer log. Therefore, you must be careful not to include pointers to other sites in pages that use this method for storing session IDs. To get around this problem, you can put the session ID in a cookie, as the next section demonstrates.
Show Contents Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |