in reply to CGI forms (basic)
login.pl:<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>
#!/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..."
|
|---|