<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Login Page</h1>
<form name="LoginForm" action="/cgi-bin/login.pl" method="post">
<table align="center">
<tr>
<td>Username:</td>
<td><input type="text" name="Username" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="Password" /></td>
</tr>
<tr>
<td colspan="2" align="right">
<input type="reset" value="Clear" />
<input type="submit" value="Login" />
</td>
</tr>
</table>
</form>
</body>
</html>
login.pl:
#!/usr/bin/perl -wT
#########################################
### Name : login.pl
### Date : December 2002
### Purpose : To provide a script that will take the input
### : of an HTML input form with Username and
### : Password fields and validate the input
### : against information stored in a Postgres
### : database on localhost.
#########################################
#BEGIN {
# print "Content-type: text/plain\n\n";
#}
use strict;
use lib qw ( . );
use CGI::Pretty;
use CGI::Session qw/-ip-match/;
use DBI;
use Constants;
$|++;
$CGI::Pretty::INDENT = " ";
require "./include/db.pl";
require "./include/validate.pl";
require "./include/hope_generics.pl";
main();
#######################################################
### Username and password match. Successful login.
#######################################################
sub print_content {
my %login = @_;
print "<div class=\"Content\">\n\n";
print "<h1>You've logged in!</h1>\n\n";
print "<p>Welcome, $login{USERNAME}</p>\n\n";
print "</div>\n\n";
$sql->finish();
db_disconnect($dbh);
}
sub debug_inputs {
my $cgi = shift;;
my %login = @_;
print $cgi->div({-class=>'Content'},
$cgi->p('Username = ' . $login{USERNAME}),
$cgi->p('Password = ' . $login{PASSWORD}),
$cgi->p('Match = ' . $login{MATCH}),
);
}
sub validate_inputs {
my $cgi = shift;
my $debug = 0;
my %login = (
USERNAME => validate_char($cgi->param('Username'), 20),
PASSWORD => validate_alphanumeric($cgi->param('Password'), 20),
VALID => 0
);
if ($login{USERNAME} ne "" && $login{PASSWORD} ne "") {
$login{VALID} = 1;
} else {
$login{VALID} = 0;
}
if ($debug != 0) { debug_inputs($cgi, %login); }
return %login;
}
sub check_password {
my %login = @_;
my $dbh = db_connect();
#######################################################
### Grab the password stored in the database for the
### username entered.
### There's a possibility that the username doesn't
### exist. This should be handled gracefully.
#######################################################
my $sql = $dbh->prepare_cached('
SELECT L_ID, L_Password
FROM Login
WHERE L_Username = ?;');
$sql->execute($login{USERNAME});
my ($db_id, $db_password) = $sql->fetchrow_array();
if ($db_password eq $login{PASSWORD}) {
$login{MATCH} = 1;
$login{USERID} = $db_id;
$sql = $dbh->prepare_cached('
INSERT INTO LoginHistory (LH_L_ID, LH_CreatedDate)
VALUES (?, CURRENT_TIMESTAMP);');
$sql->execute($db_id);
} else {
$login{MATCH} = 0;
}
$sql->finish();
db_disconnect($dbh);
return %login;
}
sub print_bad_password {
my $cgi = shift;
print $cgi->div({-class => 'Content'},
$cgi->h1("The username you entered does not exist, or the
password does not match.")
);
}
sub main {
my $cgi = create_cgi();
my $session = new CGI::Session("driver:File", $cgi,
{ Directory => $Constants::DIRECTORY });
$session->expire('+15m');
my $cookie = $cgi->cookie(CGISESSID => $session->id);
my %login = validate_inputs($cgi);
if ($login{VALID} == 1) {
%login = check_password(%login);
if ($login{MATCH} == 1) {
$session->param("USERNAME", $login{USERNAME});
$session->param("USERID", $login{USERID});
print $cgi->header( -cookie => $cookie );
print_head();
print_content(%login);
} else {
print $cgi->header();
print_head();
print_bad_password($cgi);
}
} else {
print $cgi->header();
print_head();
print_not_logged_in();
}
print_footer();
exit(0);
}
NOTE: This code is ugly, sloppy, and bad form. But it works (at least, it does on my machine where I have all the required files. print_head() basically prints from <html> up to <body>. print_footer() prints their closing tags. The validate methods basically untaint the user input from the form's textfields. db_connect() sets up all the required fields for logging into my database (Postgres, as mentioned), and does a return DBI->connect(...);. db_disconnect() simply does a $dbh->disconnect();
This could be implemented MUCH better, and more cleanly. I will be the first to admit that I have not yet worked with any of the (supposedly) great HTML templating languages provided by CPAN. That's the next step I plan to take with the application from which I've pulled this code. But, as they say..."In my spare time..."
|