intranetman has asked for the wisdom of the Perl Monks concerning the following question:

My site is using CGI::Session and MySQL to handle a member's area. Right now everything works perfectly, except of course the session handling. Whenever a user logs-in a new session id is created and stored in the MySQL user database. Whenever they logout it is destroyed. However, when the user browses to a restricted page after login, I cannot retrieve the Session from the browser. I store the session id in a cookie on the users end
.. $session->save_param($cgi); setCookie($cgi, $session); .. sub setCookie($) { my($cgi, $session) = @_; $cookie = $cgi->cookie(CGISESSID=> $session->id); print $cgi->header( -cookie=>$cookie); }
I attempt to retrieve the session as follows:
sub retriveSession() { my $cgi = new CGI; $sid = $cgi->cookie("CGISESSID") || $cgi->param('CGISESSID') || undef +; $session = new CGI::Session(undef, $sid, {Directory=>'/tmp/Sessions +/'}); if ((undef($sid)) || (undef($sessions))) { print "<li> You are currently not logged. You will now be return +ed to the login page! </li> \n"; print qq{<meta HTTP-EQUIV=REFRESH content="1; url=http://www.myu +rl.com/login.html">}; exit(0); } }
Where CGISESSID should be cache (right? wrong?). Now, I could return the cookie, but that doesn't make sense as it is supposed to be cached or written to the clients disk. So when I login I have a sessionid of say a983c8302e7a678a2e53c65e8bd3316, but when I try to retieve that value with a small script I get a new value 9ccaa7a41f78970bb804b4afa9e8cb4c.

I've read through the CGI::Session, CGI Cookie pages, and perldocs, but nothing. They keep saying that you can retrieve the session parameters using something similar  $session->load_param($cgi, ["fruits"]);, but that presupposes that the session variables is already passed.

Do I have to pass the cookie and session variables as headers to each page? This doesn't seem right as it should be kept on disk or in memory until expiration. My implementation is pretty similar to that in the Tutorial, however, I wrote my own drivers for MySQL. I thought about using CGI::Session:Serialize the process, but this adds another security issue.

I think I've confused myself. Any Perl Wisdom would be helpful, thanks once again!

Replies are listed 'Best First'.
Re: CGI::Session Handling
by punkish (Priest) on Sep 22, 2004 at 17:59 UTC
    Do I have to pass the cookie and session variables as headers to each page? This doesn't seem right as it should be kept on disk or in memory until expiration.
    "Which disk" and "which memory?" The act of saving a cookie does write the SID to disk -- the client's disk. Checking, on every page load, if the cookie exists, and if it does, setting the SID to that value, recreates the session.

    If the cookie doesn't exist, a new SID will get created. That is normal behavior, since, as far as your program is concerned, it has never seen that session before.

    All that said, I've had problems with CGI-Session as well, but only when using the ODBC driver. I eventually ended up using just a file and things worked just well.

      That makes sense. To rehash for my own understanding the cookie should technically exist on the client's disk. However, I need to check for it at each page I want to restrict access too. When it finds the cookie it then creates a new session with the old parameters.

      My next questions is how do I retrieve those old values since technically it could be looking for any CGISESSID that has been loaded. In other words, is it imperative that I pass CGISESSID to/between each html/cgi document that the client visits? I am using the following (updated) code to store and retrieve cookies:

      sub setCookie($) { my($session) = @_; my $q = new CGI; $sid = $session->id(); $cookie = $q->cookie(-name => "CGISESSID", -value => $sid, -expires => '+1h', -path => '/tmp/Sessions'); print $q->header(-cookie=>$cookie); } sub retrieveSession() { $query = new CGI; $sid = $query->cookie("CGISESSID") || undef; $session = new CGI::Session(undef, $sid, {Directory=>'/tmp/Session +s'}); $sid = $session->id(); $session = getUser($sid); print $session->param("log_name"); return $session; } sub getUser($) { my ($sid) = @_; $select = "SELECT username, password FROM Employees WHERE session_i +d = '$sid'"; $get_it = $db->prepare($select); $get_it->errstr, "\n"; $rv = $get_it->execute() or die "Couldn't execute query '$select' \ +n"; $get_it->bind_columns(undef, \$username, \$password); $get_it->fetchrow_arrayref(); $session->param(-name=>"log_name", -value=>$username); $session->pa +ram(-name=>"log_password", -value=>$password); return $session; }
      Even though I have a cookie stored on disk that I can see the getUser and retrieveSession functions are not working properly. I would think that I wouldn't need to append cgisess_ to the beginning of the session id like cgisess_a983c8302e7a678a2e53c65e8bd3316 because it should take care of this automatically? Any other ideas? Thanks once again for helping out!
        That makes sense. To rehash for my own understanding the cookie should technically exist on the client's disk. However, I need to check for it at each page I want to restrict access too. When it finds the cookie it then creates a new session with the old parameters.
        You are mostly correct, except for the last part. When a cookie is found, a new session is not created... instead, the old session is recreated.

        The old session is recreated with the help of the cookie. The cgi method for cookie essentially retrieves the cookie if it exists, and SID is set to that value. If the cookie doesn't exist, a new cookie gets created (using MD5), and SID is set to that.

        I don't have my scripts with me that I used to create a succesful app, but here is my advise. Start small. Ditch your home-rolled MySQL driver for now, and just use the File option in the CGI-Session module. Use the cookbook recipe for creating a members-only area. Once that is working, then apply your MySQL driver. That way you will know where the problem lies. Always solve one variable at a time. Too many unknowns always spell doom for the programmer.

        Good luck.

        Sorry, that cgisess_a983c8302e7a678a2e53c65e8bd3316 value is the session be stored not the cookie. The cookie does not work...and I'm so hungry...(the directory has the correct read/write permissions as well)!! AHHH!