Re: [Cgi-session-user] how load works (was: MySQL backend - multiple copies of session id's stored?
Brought to you by:
sherzodr
From: Justin S. <ju...@sk...> - 2006-07-30 23:41:49
|
> There's probably a bug here. Could you boil this down to a Test::More > style test case? It looks like you are nearly there. Done! Be gentle - this is my first real Test::More test - I know these are supposed to be pretty simple, but setting up all the DBI parameters seems a bit verbose, but I've attached it to this message, as well as attempted to place it inline (notes to follow code): [snip] #!/usr/bin/perl use Test::More tests => 4; use CGI::Session; use DBI; # SQL Paramaters - obviously, these will be different from you... my %sql_params = ( database => 'database', dbserver => 'localhost', # may just be, "localhost" port => '3306', # mysql: 3306, Postgres: 5432 dbtype => 'mysql', # 'mysql' for 'MySQL', 'Pg' for 'PostgreSQL' user => 'user', pass => 'pass', session_table => 'sessions', ); # Let's get a db handle... my $dbh = connectdb( $sql_params{dbtype}, $sql_params{database}, $sql_params{dbserver}, $sql_params{3306}, $sql_params{user}, $sql_params{pass}, ); # Some CGI::Session params... my $dsn = 'driver:mysql'; my $dsn_args = { Handle => $dbh, TableName => $sql_params{session_table}, }; # Let's start with a clean slate... $dbh->do("DELETE FROM " . $sql_params{session_table}); # Build us a session object... my $session = new CGI::Session($dsn, undef, $dsn_args); $session->param('foo', 'bar'); $session->expire('+1d'); $session->flush(); # Check the integrity of our saved information.... ok($session->param('foo') eq 'bar', "Correct information has been saved in the session..."); # Save this for later, so we can recall the info... my $session_id = $session->id; # Hey, let's see how many rows we have... my $sth = $dbh->prepare("SELECT COUNT(*) FROM " . $sql_params {session_table} ); $sth->execute(); # (Hopefully) we only have one session... ok($sth->fetchrow_array() == 1, "Only one copy of the session file..."); # In the app itself, the Session is checked upon a refresh to a new screen... # So let's get rid of what we have, and do it again... undef $session; undef $dbh; # just being thorough. # Our new DB handle... # There's no persistance in the CGI app... my $dbh2 = connectdb( $sql_params{dbtype}, $sql_params{database}, $sql_params{dbserver}, $sql_params{3306}, $sql_params{user}, $sql_params{pass}, ); # And again.. my $dsn2_args = { Handle => $dbh2, TableName => $sql_params{session_table}, }; # New Session! Should call up the same information... my $session2 = CGI::Session->load($dsn, $session_id, $dsn2_args); # Check the integrity of our saved information.... ok($session2->param('foo') eq 'bar', "Information is retrieved from past session alright..."); # NOTE: UNCOMMENTING EITHER OF THESE TWO LINES WILL CAUSE THE NEXT TEST TO FAIL # $session2->flush; # undef $session2; # ??? # How many do we have?! my $sth2 = $dbh2->prepare("SELECT COUNT(*) FROM " . $sql_params {session_table} ); $sth2->execute(); # One? Two? ok($sth2->fetchrow_array() == 1, "Still only one copy of the session..."); # This is to double check out handy work: # print "\n\nLet's see what's in the table:\n" . '-' x 72 . "\n"; my $sth3 = $dbh2->prepare("SELECT * FROM " . $sql_params {session_table} ); $sth3->execute(); $sth3->dump_results(2048); [/snip] NOTES: I tried to emulate how things are running in the (I admit, complex) web app - does a good job. In the web app, upon login, a session is created, and set in a cookie. The person will receive the cookie and the page will refresh to the administration side of things - that's why there's the creation of a new session (and db handle, etc). Plop in your own DB credentials, obviously. All the above tests (4) PASS - until you uncomment one of the two lines: Either: # $session2->flush; or: # undef $session2; For whatever reason, this will write a second, similar session into the table, with the same session id and same parameters saved. And that's leading to some problems. I've only tested this on a server running mysql, but it doesn't (without testing) seem to be a problem with Postgres which is a little mysterious. Here's the output if you uncomment one of the above lines: me@there [~/where/we/are]# perl dup_sess.pl 1..4 ok 1 - Correct information has been saved in the session... ok 2 - Only one copy of the session file... ok 3 - Information is retrieved from past session alright... not ok 4 - Still only one copy of the session... # Failed test (dup_sess.pl at line 123) Let's see what's in the table: ------------------------------------------------------------------------ 'c211b11dc99e01c9f5685fd39391d6eb', '$D = {'_SESSION_ETIME' => 86400,'_SESSION_ID' => 'c211b11dc99e01c9f5685fd39391d6eb','_SESSION_ATIME' => 1154302807,'foo' => 'bar','_SESSION_REMOTE_ADDR' => '','_SESSION_CTIME' => 1154302807};;$D' 'c211b11dc99e01c9f5685fd39391d6eb', '$D = {'_SESSION_ID' => 'c211b11dc99e01c9f5685fd39391d6eb','_SESSION_ETIME' => 86400,'_SESSION_ATIME' => 1154302807,'foo' => 'bar','_SESSION_EXPIRE_LIST' => {},'_SESSION_REMOTE_ADDR' => '','_SESSION_CTIME' => 1154302807};;$D' 2 rows # Looks like you failed 1 test of 4. me@there [~/where/we/are]# Thanks Mark for showing me how to whip up Test's :) Justin Simoni -- :: is an eccentric artist, living and working in Denver, Colorado :: URL: http://justinsimoni.com :: PHO: 720.436.7701 :: Mailing List - http://justinsimoni.com/mailing_list.html |