Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is $auth->loggedIn never true in my use of CGI::Session::Auth::DBI?

Using the examples from the CGI::Session::Auth::DBI and CGI::Session::Auth pages, I have attempted to implement the _login function with no success. I'm using Windows 7 and Apache 2.

#!/usr/bin/perl -w
use strict;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use CGI::Session;
use CGI::Session::Auth::DBI;

my $cgi = new CGI;

# using '.' directory for testing
my $session = new CGI::Session(undef, $cgi, {Directory=>'.'});
my $auth = new CGI::Session::Auth::DBI({
    CGI => $cgi,
    Session => $session,
    DSN => 'dbi:mysql:dbname=foobar:host=localhost',
    DBUser => 'foo',
    DBPasswd => 'bar',
    UserTable => 'cgi_auth_user' # auth_user already in use
});

print "Content-type: text/html\n\n";

if ($auth->_login("admin", "admin")) {
    print "<p>login ok</p>";
} else {
    print "<p>login fail</p>";
}

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}

The rendered output from this is:

login ok
not logged in

If I change the values passed to _login to "foo", "bar" (an invalid username/password), then I get this rendered result:

login fail
not logged in

I'm using '.' just for testing as I know it's a dir I can write to. Every time I run the code, a cgisess_ file is created (e.g. cgisess_9fb493cc9155ee9dd2b18fddc38139d8), but this is created regardless of if I use a correct username or not. No errors are being returned, but $auth->loggedIn is always false.

The documentation says that _login is virtual, and it sounds like the DBI module overrides this, but I'm not sure.

What could I be doing wrong?

Update 1:

I've also tried using $auth->authenticate() before the call to $auth->loggedIn but this has no effect. I've also tried using $auth->authenticate() and $auth->loggedIn on another after successful login, but I get the same result. No matter what I do, $auth->loggedI is always false.

Update 2:

I've also tried chaning the directory to "/" and all it does is create the cgisess files in / rather than current dir.

Update 3:

I figured it may be an issue with the database records; I'm using the default example ones from the example page, but with a modified admin password. Here's a phpMyAdmin export:

CREATE TABLE IF NOT EXISTS `cgi_auth_user` (
  `userid` char(32) collate utf8_unicode_ci NOT NULL,
  `username` varchar(30) collate utf8_unicode_ci NOT NULL,
  `passwd` varchar(30) collate utf8_unicode_ci NOT NULL default '',
  PRIMARY KEY  (`userid`),
  UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `cgi_auth_user` (`userid`, `username`, `passwd`) VALUES
('325684ec1b028eaf562dd484c5607a65', 'admin', 'admin'),
('ef19a80d627b5c48728d388c11900f3f', 'guest', 'guest');

Then again, if _login is returning true with a valid username and password, then I would assume that the userid is valid... No?

Update 4:

I've also tested this on our Linux production server, and I get the exact same issue.

like image 702
Nick Bolton Avatar asked Jan 10 '10 23:01

Nick Bolton


2 Answers

The doc is pretty clear that you have to override the _login() method, unless guest/guest works for you. Plus you aren't calling authenticate(), which actually invokes _login(), you shouldn't be doing it.

_login()

This virtual method performs the actual login attempt by comparing the login form data the visitor sent with some local user database. The _login method of the base class CGI::Session::Auth only knows the user 'guest' with password 'guest'.

To access a real user database, you have to use a subclass that modifies the _login method appropriately. See the modules in the Auth/ subdirectory.

like image 29
ergosys Avatar answered Sep 29 '22 15:09

ergosys


Try outputting the results of $session->header() as the first thing you output. This should set your cookie and load the existing session instead of creating a new one each time.

Also, _login() only performs the authentication with the database, but does not modify the $auth object. Using authenticate(), you need to define the username and password using the param() function of your $cgi object. You need to set the fields log_username and log_password for the authenticate() function to work.

#!/usr/bin/perl -w
use strict;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use CGI::Session;
use CGI::Session::Auth::DBI;

my $cgi = CGI->new;
my $session = new CGI::Session(undef, $cgi, {Directory=>'/tmp'});

my $auth = new CGI::Session::Auth::DBI({
    CGI => $cgi,
    Session => $session,
    DSN => 'dbi:mysql:dbname=foobar:host=localhost',
    DBUser => 'foo',
    DBPasswd => 'bar',
    UserTable => 'cgi_auth_user'
});

print $session->header();

$cgi->param('log_username', 'admin');
$cgi->param('log_password', 'admin');

$auth->authenticate();

if ($auth->loggedIn) {
    print "<p>logged in; go to <a href='index.pl'>index</a></p>";
} else {
    print "<p>not logged in</p>";
}

I haven't tested it, but this should be working.

like image 153
Signal Avatar answered Sep 29 '22 16:09

Signal