Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

CGI::Session keeps re-using same session ID

by alain_desilets (Beadle)
on May 01, 2012 at 17:45 UTC ( #968308=perlquestion: print w/replies, xml ) Need Help??
alain_desilets has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to implement a simple login dialog for my application, and am having trouble making it work.

Below is a small piece of code that illustrates my problem:

#!C:/Perl/bin/perl use strict; use warnings; use CGI::Carp qw( fatalsToBrowser ); use CGI; use CGI::Session; run(); sub run { my $cgi = new CGI(); my $action = $cgi->param('do'); # # Create a session object # my $session = undef; if ($action eq 'login') { # Create a brand new session, by passing an undef cgi argument + to CGI::Session. $session = new CGI::Session("driver:File", undef, {Directory=> +"/"}); } elsif ($action eq 'stay_logged') { # Keep the existing session, by passing the CGI object to CGI: +:Session. $session = new CGI::Session("driver:File", $cgi, {Directory=>" +/"}); } else { die "Invalid action '$action'\n"; } # # Send the CGISESSID cookie to the browser # my $cookie = undef; my $session_id = undef; if ($session) { $session_id = $session->id(); $cookie = $cgi->cookie(CGISESSID => $session_id); print $cgi->header(-cookie=>$cookie); } print $cgi->start_html('Fooling around with session login/logout') +; print "<h3>\$action='$action'</h3>\n"; print "<pre>\$session_id=$session_id\n</pre>\n\n"; print "<pre>\$cookie=$cookie\n\n</pre>\n"; my $random_id = rand(); print "<ul>\n"; print " <li><a href=\"try_logon.cgi?do=login&rand=$random_id\">l +ogin</a></li>\n"; print " <li><a href=\"try_logon.cgi?do=stay_logged&rand=$random_ +id\">stay logged</a></li>\n"; print "</ul>\n"; print $cgi->end_html; }

This script displays a 'login' and a 'stay logged' links. The 'login' link is supposed to create a brand new session (line 21), by invoking new CGI::Session::new() and passing it an undefined value for the CGI argument. The 'stay logged' link is supposed to create a session using the current session ID (line 24), by passing an actual CGI instance as the second argument of CGI::Session::new().

But it doesn't work!

If I click multiple times on the 'login' dialog, I see the same session id being used over and over again. Same goes for the 'stay logged' link, but that one is to be expected.

Note that I am running under mod_cgi (NOT mod_perl), and that it can't be a cache issue, because the URL of each of the invocations of the script is different (because I add a different random cgi argument to it everytime).

What am I doing wrong? Thx.

Replies are listed 'Best First'.
Re: CGI::Session keeps re-using same session ID
by Anonymous Monk on May 02, 2012 at 06:17 UTC

      Thx for the tips. I'm not one to reinvent the wheel. I have spent the last 48 hours looking for an easy way to do sessions and mostly what I find are things like the documentation and tutorials for CGI::Session and Apache::Session, all of which seem to be very barebone.

      I did find out about CGI::Application, but I'm reluctant to use it for two reasons:

      a) CGI::Application assumes that the HTML for a transaction gets accumulated into a scalar string, and then printed all at once at the end. My application can't afford to do that, because it is a search engine that typically takes 2 minutes to complete the search. It can't afford to wait those two minutes before displaying some results. Instead, it needs to display each search result as soon as it finds it. Maybe I could inherit from CGI::Application and inject a hook into it for printing html as soon as it gets generated, but that sounds like it would be very involved.

      b) I already have a large application to which I need to add session support. I would have to do a major rewrite to cast it into the CGI::Application framework.

      I'll look at some of the other links you provided, and hopefully I'll find what I need there. Alain

        I did find out about CGI::Application, but I'm reluctant to use it for reason a

        To stream from CGI::Application see the docs, search for "stream", it also links the practical example CGI::Application::Plugin::Stream. Basically, in your target runmode, print the headers immediately, signal CGI::Application not to print any headers when the runmode returns, and then just prints the content one chunk at a time, and return nothing.

Re: CGI::Session keeps re-using same session ID
by scorpio17 (Abbot) on May 02, 2012 at 16:15 UTC
    You need to look at using CGI::Cookie also. You're writing a cookie with the session ID in it, but you're not reading it back. Reading the session ID from the cookie is the first thing you should do. If there is no cookie/session ID, then you know it's a visitors first time - create a new session for them. If you DO find a session ID in the cookie, then they're a repeat visitor: use the ID to reload their session. Data in the session can be used to modify the page you display (i.e., if someone is logged in, display a "logout" button, else display a "login" button", etc.)

      You're writing a cookie with the session ID in it, but you're not reading it back

      CGI::Session->new does the reading of the cookie

Re: CGI::Session keeps re-using same session ID
by Anonymous Monk on May 02, 2012 at 14:39 UTC
    Not sure if this would work for you:
    my $session = CGI::Session->load("driver:File", undef, { Directory=>$s +ession_dir->{users} }); if ($session->is_empty) { $session = CGI::Session->load("driver:File", undef, { Directory=>$ +session_dir->{tmp} }); }
Re: CGI::Session keeps re-using same session ID
by sundialsvc4 (Abbot) on May 02, 2012 at 11:44 UTC

    In addition to the admonition, “do not do a thing already done,” session handling code normally does not rely particularly on the browser to keep or not-keep the cookie.   Instead, it deletes the database-record corresponding to that cookie value.   The user is considered to be “logged on” only if the cookie in some way corresponds to a database record that exists and that says the user is logged on.   Even if the same session-ID cookie somehow keeps coming up again and again, what matters is what is happening on the host.

      I understand that you should not rely solely on the presence or absence of a cookie to decide if the user is logged on or not. I was just providing a small sample code to illustrate the fact that I am unable to save a new session ID cookie to the browser. I'm astonished at how difficult sessions are to get working, even for an experienced Perl programmer like me.

        I'm astonished at how difficult sessions are to get working, even for an experienced Perl programmer like me.

        I'm not :) HTTP is complicated enough, and then you have to deal with implementation details of and

        CGI::Session->new will try to load a session first, and only create a new session if it fails to load one

        The thing is, since in CGI protocol, cookies are retrieved via $ENV{HTTP_COOKIES}, if there is a cookie set, CGI::Session will always load an existing session, because (or will always read $ENV{HTTP_COOKIES}

        Hopefully you have read Basic cookie management (May 01) by now,

        but here is how you fix your program without changing the program flow,

        you delete the session if you can load it, then you create a new one

        if ($action eq 'login') { $session = CGI::Session->load( "driver:File", undef, $dsn_args ); eval { $session->delete; $session->flush; }; $session = CGI::Session->new( "driver:File", undef, $dsn_args ) or die CGI::Session->errstr; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://968308]
Approved by MidLifeXis
Front-paged by MidLifeXis
and cookies bake in the oven...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2018-03-18 03:03 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (228 votes). Check out past polls.