Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Problems with session expiration

by Digioso (Sexton)
on Jan 01, 2014 at 12:42 UTC ( [id://1068857]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all,

I'm trying to build a login-system based on CGI::Session.

I have the registration, login and logout running so far but I currently have an issue that a session seems to get deleted after about 10 seconds or so automatically. I tried using something like $session->expire('+1h'); to force a session expiration date but this does not seem to work.

My code so far:

Navi.pm (this module basically prints the navigation on my website, html-meta-tags, CSS and so on).

This module is included in all my files:

Relevant code:

Navi::print_navi function:
print $cgi->header(-cache_control=>"no-cache, no-store, must-revalid +ate"), # create the HTTP header $cgi->start_html(-title=>"$title", -author=>'webmaster at digioso.org', -meta=>{long list of meta information here........., -style=>{'src'=>'http://www.digioso.org/style.css'}); +# start the HTML

Navi::end_navi function basically prints some stuff and then finally ends with print $cgi->end_html;

Now for the code that directly affects the login:

login.pl : That file creates a new session and logs the user in. If successful redirects to index.pl
#!/usr/bin/perl -w use warnings; use strict; use CGI; use CGI::Carp qw/fatalsToBrowser warningsToBrowser/; use Digest::MD5 qw(md5_base64); use CGI::Session; use lib "<path to my libraries on that server>"; use Navi; use DB; my $cgi = CGI->new(); my $dbh = DB::connect_db(); my $usr = $cgi->param('usr'); my $pwd = $cgi->param('pwd'); if($usr ne '') { my $encrpass = md5_base64($pwd); my $sql = qq{SELECT id FROM consystem_users WHERE username=? and p +assword=?}; my $sth = $dbh->prepare($sql) or die $dbh->errstr; $sth->execute($usr, $encrpass) or die $sth->errstr; my $userid = $sth->fetchrow_array; if($userid != "") { my $session = new CGI::Session(); $session->param("uid", $userid); $session->expire('+1h'); print $session->header(-location=>'index.pl'); } else { Navi::print_navi(": digioso :"); # Print Navigation print qq{<div id="category">[ LOGIN ]</div>}; print "Username or password wrong !<br/><a href='login.pl?acti +on=login'>Try again.</a>"; Navi->end_navi(); } } elsif($cgi->param('action') eq 'logout') { my $session = CGI::Session->load() or die CGI::Session->errstr; $session->delete(); print $session->header(-location=>'login.pl'); } elsif($cgi->param('action') ne 'login' && $usr eq "") { Navi::print_navi(": digioso :"); # Print Navigation print "<br/><br/>Please input username and password !"; print_login(); } else { Navi::print_navi(": digioso :"); # Print Navigation print_login(); } sub print_login() { print qq{<br/><br/><form method="post"><table> <tr><td>Username:</td><td><input type="text" name="usr"></td>< +/tr> <tr><td>Password:</td><td><input type="password" name="pwd" ma +xlength="30"></td></tr></table><br/> <input type="submit" value="Submit"> </form> <br/>You don't have an account? Create one <a href="register.p +l">here</a>.}; Navi->end_navi(); } DB::close_db(); exit 0;
index.pl: Currently doesn't really have any content.
#!/usr/bin/perl -w use warnings; use strict; use lib "<path to my libraries on that server>"; use CGI; use CGI::Carp qw/fatalsToBrowser warningsToBrowser/; use login_check; use Navi; my $cgi = CGI->new(); my $uid = login_check($cgi, ": Digiosos Con-System :"); if($uid > 0) { print qq{ $uid <a href="test.pl">Test</a>}; Navi->end_navi(); } exit 0;
Index.pl includes the login_check module. Since my login-system has more than one file I don't want to have the same code in each of them.

login_check.pm: This module checks (or at least it's supposed to do... That's my whole problem...) whether a user has a valid session or not. If yes, the login_check function returns the userid stored in $session->param("uid"). If not it returns -1 .
My problem is that $session->is_empty returns true after being idle for about 10 seconds. As long as I click around everything's fine, but leaving it idle deletes my session.
#!/usr/bin/perl -w use warnings; use strict; use lib "<path to my libraries on that server>"; use Navi; use CGI::Carp qw/fatalsToBrowser warningsToBrowser/; use CGI::Session; sub login_check($$) { my $cgi = shift; my $title = shift; my $session = CGI::Session->load(); Navi::print_navi("$title", 1); # Print Navigation if($session->is_expired) { print qq{<div id="category">[ LOGIN ]</div>}; print "Your has session expired. Please login again."; print "<br/><a href='login.pl>Login</a>"; Navi->end_navi(); return -1; } elsif($session->is_empty) { print qq{<div id="category">[ LOGIN ]</div>}; print "You have not logged in.<br/><a href='login.pl'>Login</a +> "; Navi->end_navi(); return -1 } else { print qq{<div id="category">[ CON-SYSTEM ]</div>}; print "<a href='index.pl'>Index-Page</a> <a href='changepw.pl' +>Change Password</a> <a href='login.pl?action=logout'>Logout</a><br/> +<br/>"; return $session->param("uid"); } } 1;

Thanks in advance. :)

Replies are listed 'Best First'.
Re: Problems with session expiration (there is no session)
by Anonymous Monk on Jan 02, 2014 at 02:24 UTC
      Any particular reason to make your own from scratch like that?

      Nope, but I wasn't able to find completely finished systems on Google. Or better said I found exactly one that was way over the top and I had to pay for it.

      If you know where I can find a complete system I'm willing to use it. :) How do you come to the conclusion that this code doesn't run?
      I have it running here: http://www.digioso.org/consystem/login.pl
      Test-Account:
      Login: test
      PW: test123


      But yes, I'm gonna have to read and find out more if I want it to run.
        That last post was from me. :)
Re: Problems with session expiration
by Anonymous Monk on Jan 02, 2014 at 15:09 UTC
    This sounds a whole lot more like the classic problem where a session is not actually being created, due to programmer-misunderstanding of exactly how cookies are handled in HTTP / a web-browser. Put your browser in debug mode (e.g. Firebug, developer-windows, etc.) and watch how the set-cookie: messages are being delivered and whether a cookie is actually being established on your end. Very often, they are not. A give-away that you are doing it wrong is if a very large number of sessions are being created on the server side, basically one per exchange, but never being used. If my guess is right, it's not per se a Perl problem, but programmer-error. There is a reason why most sites have a distinct /login page ...
      Hmm, okay. Since the Session Tutorial said that we can use server-side-session management (= No cookies) I thought that this is what I was doing. So I'm wrong here, correct? I don't want any cookies.
      And I do have a separate login page.

        Hmm, okay. Since the Session Tutorial said that we can use server-side-session management (= No cookies) I thought that this is what I was doing. So I'm wrong here, correct? I don't want any cookies. And I do have a separate login page.

        Ok, you can consider this a follow up to Re^4: Problems with session expiration (there is no session)

        no cookies means no session ;

        $session->header sends cookies

        if you don't want cookies, you can communicate the session id through link rewriting, like "/sessionid/link" or "/link?sessionid" or "/link?id=sessionid"

        or through hidden form field ... but then all your links have to be buttons

        your code as written doesn't actually do this

        A session is just an id associated with a browser, browser communicates sessionid to server via cookie/urlparam/formparam .... server looks up sessionid in database (or wherever) to retrieve data associated with sessionid

        is that clearer?

        Another alternative to cookies is Digest access authentication which is just another HTTP header (like cookies)
        Mojolicious::Plugin::DigestAuth - HTTP Digest Authentication for Mojolicious
        Plack::Middleware::Auth::Digest - Digest authentication

        Catalyst::Plugin::Session::Manager::Client::Rewrite - handle sessonid with rewriting URL
        Catalyst::Plugin::Session::State::URI - Use URIs to pass the session id between requests

        Good luck

Re: Problems with session expiration
by stonecolddevin (Parson) on Jan 03, 2014 at 22:02 UTC

    Refactor your code to use Plack + Plack::Middleware::Session. Your life will be much easier and you'll get on track with modern and practical web application development practices.

    Three thousand years of beautiful tradition, from Moses to Sandy Koufax, you're god damn right I'm living in the fucking past

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1068857]
Approved by Corion
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (7)
As of 2024-04-18 02:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found