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

Hello. I'm new to CGI::Session. I've looked through the documentation but have become stuck. I seem to have a problem with correctly passing session info from one page to another. Your help is appreciated.

I will include code for two pages. I have stripped out most of the code that is not relevant to this question.

login.pl ... on this page I am attempting to setup a new session.

page.pl ... on this page I am attempting to grab that session info to confirm that the user is logged in.

If it matters I am Win 10, IIS, Perl 5, SQLite. The database connections seem to work because I am able to query the database and see new sessions being stored.

My test goes as...

1. Go to login.pl (I have rigged the page to set a login... again trying to solve one problem at a time) and on this page the user_logged_in parameter is set as true.

2. Go to page.pl to see if the session data, particularly user_logged_in parameter was accessed.

Result: When I do this and go to page.pl I see a new Session ID and it does not get the user_logged_in parameter as being set as true.

login.pl
### Setup environment use CGI; use CGI::Carp qw(fatalsToBrowser); use CGI::Session; use CGI::Session qw/-ip-match/; use DBI; use strict; use warnings; my $dbfile = "/inetpub/wwwroot/data/people1.db"; my $dsn = "dbi:SQLite:dbname=$dbfile"; my $user = ""; my $password = ""; my $dbh = DBI->connect($dsn, $user, $password, { PrintError => 0, RaiseError => 1, AutoCommit => 1, FetchHashKeyName => 'NAME_lc', }); ### Setup session data connection my $cgi = new CGI; my $session = CGI::Session->new("driver:sqlite", undef,{DataSource=>'/ +inetpub/wwwroot/data/session_management.db'}) or die (CGI::Session->errstr); my $cookie = $cgi->cookie(CGISESSID => $session->id ); print $cgi->header(-cookie=>$cookie); ### Test set variables # Skip the logic for authenticating a user for testing purposes only. $session->param("user_logged_in", 'true'); ### Grab SID my $sid = $session->id(); ###For testing only. Basically in previous line did I correctly set t +he parameter to a flag a user as logged in. my $session_status = $session->param("user_logged_in"); my $login_trials = init(); sub init { #if ( $session->param("~logged-in") ) { # return 1; # if logged in, don't bother going further # } # if we came this far, the login/psswds do not match # the entries in the database my $trials = $session->param("~login-trials") || 0; return $session->param("~login-trials", ++$trials); } ### Print HTML document my $html = "Content-Type: text/html <HTML> <HEAD> <TITLE>Session Test</TITLE> </HEAD> <BODY> <H4>Create a new session</H4> <P> <p> Session ID: $sid; <p> Session status: $session_status; <p> login_trials: $login_trials; <p> </BODY> </HTML>"; print $html;

page.pl

### Setup environment use CGI; use CGI::Carp qw(fatalsToBrowser); use CGI::Session; use CGI::Session qw/-ip-match/; use DBI; use strict; use warnings; my $dbfile = "/inetpub/wwwroot/data/people1.db"; my $dsn = "dbi:SQLite:dbname=$dbfile"; my $user = ""; my $password = ""; my $dbh = DBI->connect($dsn, $user, $password, { PrintError => 0, RaiseError => 1, AutoCommit => 1, FetchHashKeyName => 'NAME_lc', }); ### Setup session data connection my $cgi = new CGI; my $sid = $cgi->cookie("CGISESSID") || undef; my $session = CGI::Session->new("driver:sqlite", $sid,{DataSource=>'/i +netpub/wwwroot/data/session_management.db'}) or die (CGI::Session->errstr); ### Grab variables from the session my $sid = $session->id(); my $session_status = $session->param("user_logged_in"); my $login_trials = init(); sub init { #if ( $session->param("~logged-in") ) { # return 1; # if logged in, don't bother going further # } # if we came this far, the login/psswds do not match # the entries in the database my $trials = $session->param("~login-trials") || 0; return $session->param("~login-trials", ++$trials); } ### Print HTML document my $html = "Content-Type: text/html <HTML> <HEAD> <TITLE>Session Test</TITLE> </HEAD> <BODY> <H4>Check existing session data and status</H4> <P> <p> Session ID: $sid; <p> Session status: $session_status; <p> login_trials: $login_trials; <p> </BODY> </HTML>"; print $html;

Replies are listed 'Best First'.
Re: CGI Session not passing session info between pages
by bliako (Abbot) on Apr 01, 2018 at 09:32 UTC
    $session->flush(); at the end of login.pl helped me a lot.

      In the tutorial on CGI::Session there is the excerpt I paste at the end.

      What I understand from it is that at the end of your login script session should automatically be flush()ed, close()d and destroyed.

      Why is flush() not happening then?

      CLOSING THE SESSION
      
      Normally you don't have to close the session explicitly. It gets closed when your program terminates or session object goes out of scope. However in some few instances you might want to close the session explicitly by calling CGI::Session's close() method or undefining the object. What is closing all about - you'd ask. While session is active, updates to session object doesn't get stored in the disk right away. It stores them in the memory until you either choose to flush the buffer by calling flush() method or destroy the session object by either terminating the program or calling close() method explicitly.
      
      In some circumstances you might want to close the session but at the same time don't want to terminate the process for a while. Might be the case with GUI and in daemon applications. In this case close() is what you want. Note: we prefer simpl undefing the session rather than calling close() method. close() is less efficient):
      
          undef($session);
      
      If you want to keep the session object but for any reason want to synchronize the data in the buffer with the one in the disk, flush() method is what you need.
      
      Note: close() calls flush() as well. So there's no need to call flush() before calling close()
        Why is flush() not happening then?

        This puzzled me for some time. What I found was that if you replaced the init subroutine (with inline code) the OP code works. I think the reason is the order in which the session and dbh object are destroyed. With $session in the sub, the dbh is destroyed first preventing the data from being synchronized.

        poj
Re: CGI Session not passing session info between pages
by poj (Abbot) on Apr 01, 2018 at 14:14 UTC

    As bliako said, use $session->flush(). Here is minimal example

    #!perl # login.pl use strict; use warnings; use CGI; use CGI::Carp qw(fatalsToBrowser); use CGI::Session; use DBI; my $dir = '/inetpub/wwwroot/data/'; my $dsn = $dir.'session_management.db'; my $session = CGI::Session->new("driver:sqlite", '', {DataSource=>$dsn}) or die (CGI::Session->errstr); # '' to create new session my $sid = $session->id(); $session->param("user_logged_in", 'true'); $session->flush; my $cgi = new CGI; print $session->header(); print $cgi->start_html("Session Test"); print $cgi->h4('Create New Session'), $cgi->pre("SID : $sid"), $cgi->a({href=>'page1.pl'},"Goto Page 1"), $cgi->end_html;
    #!perl # page1.pl use strict; use warnings; use CGI; use CGI::Carp qw(fatalsToBrowser); use CGI::Session; use DBI; my $dir = '/inetpub/wwwroot/data/'; my $dsn = $dir.'session_management.db'; my $session = CGI::Session->new("driver:sqlite", undef , {DataSource=>$dsn}) or die (CGI::Session->errstr); my $sid = $session->id(); my $session_status = $session->param("user_logged_in"); my $text = " Session ID: $sid; Session status: $session_status"; my $cgi = new CGI; print $cgi->header(); print $cgi->start_html("Session Test"); print $cgi->h4('Check status'), $cgi->pre($text), $cgi->a({href=>'login.pl'},"Goto Login"), $cgi->end_html;
    poj
Re: CGI Session not passing session info between pages
by RedJeep (Sexton) on Apr 02, 2018 at 03:07 UTC
    My Perl friends, Thanks so much for the quick replies. I'll post the results. Again, thanks a bunch!!!

    Edit: Just tried... works perfect.  $session->flush();

    Also, I'll look through the other recommendations as there is some considerable wisdom that you all have shared in helping me to write more effective code.
A reply falls below the community's threshold of quality. You may see it by logging in.