Password Protection with PHP, MySQL,
and Session Variables
by Dan McConkey
One of the great promises that actually came true when our Internet-enabled
world reached the twenty-first century is efficient customer-to-business
interaction. Each day, I find a new way to go through life's errands
without ever waiting on hold for a bank teller, a pharmacist, or
an insurance agent. I do it all online.
Internet savvy consumers are coming to expect such web empowerment.
And while these information transactions usually require some sort
of private data traveling the ether, you, as the webmaster, bear
the burden of keeping that data away from those who have no right
to it.
Since retina scans and brain wave signatures are still properties
of James Bond flicks, we're stuck using plain old boring passwords.
Is this really secure?
Let's get this out of the way first. The only truly secure computer
is one that's unplugged. Kind of like "the only safe car is
the one that sits in your garage." Life is a risk/reward proposition
and, let's face it, this (probably) isn't Fort Knox, we're securing.
The security measures listed here are suitable for garden-variety
data. I've used these schemes to write back-end website administration
pages for online shopping carts. I've used them to write "partner"
pages where retailers can download ads and sales data from wholesalers.
I wouldn't use them to secure credit card numbers, social security
numbers, or nuclear launch codes.
So what are PHP, MySQL, and session variables?
PHP is a programming language used (in this case) to write HTML.
MySQL is a database. Session variable are used by web servers to
track information from one page on a domain to another. This article
isn't a how-to for either technology. If you aren't very comfortable
with them, you could just copy and paste the code samples in this
article and build yourself a basic password protected website. You
could also just read the Cliff's notes for Pride and Prejudice and
get a C+ in literature class. Your choice.
Let's get started with sessions
It's often been said that the web is "stateless", meaning
that each web page is entirely independent, needing no other page
to exist, and taking no information from the previous page. This
is great for anonymous surfing from one site to the next, but it
stinks for password protection. Consumers want password protected
information, but they don't want to enter their password on every
page. So we turn to our web server to keep track of a user while
he's on our site.
Ex. 1.
<?php
session_start();
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://
www.w3.org/ TR/ xhtml1/ DTD/ xhtml1-strict.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml"" xml:lang="en"
lang="en">
<head><title>Dan McConkey's Free Web Marketing Guide</title></head>
<body>
<p>Dan McConkey's Free Web Marketing Guide</p>
</body>
</html>
end Ex. 1
session_start() is a PHP function that looks to see if a session
has already been started then does one of two things:
1. If a session has been started, it does nothing.
2. If a session has not been started, it begins one.
It is important to note that session_start() must occur before
any other PHP on the page, if you want it to work. Begin every password-protected
page with it. Validation
Now let's think basic validation. What sorts of things do we need
to accomplish?
* First, we need to check to see if the user has already logged
in, so we don't ask for a password on every page. If our user has
already logged in, we pass him or her through to the secure content.
* If the user hasn't already logged in, we need him or her to do
so. So we need to write a log-in form.
* We need next to compare log-in form results with a known list
of usernames and passwords. If the user checks out, we pass him
or her along to the secure content.
* If the user doesn't check out, we direct him or her back to the
log-in screen.
* Lastly, we need to provide the user the ability to log out.
So let's start with a basic frame-work that we'll fill in later.
Ex. 2
<?php
// start session if not already started
session_start();
// check to see if user just logged out
if ( $log_out )
{
}
function write_log_in( $text )
{
} // end write_log_in function
function verify()
{
// check to see if they're already logged in
// if yes, return true
// if no, check to see if visitor has just tried to log on
// if yes, verify password
// if it worked, return true
// if it didn't, send them back to log-in
// if the user didn't just log-in, (s)he needs to
} // end verify function
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://
www.w3.org/ TR/ xhtml1/ DTD/ xhtml1-strict.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml"" xml:lang="en"
lang="en">
<head><title>Dan McConkey's Free Web Marketing Guide</title></head>
<body>
<p>Dan McConkey's Free Web Marketing Guide</p>
<?php
// check for valid user
if ( verify() )
{
// begin secure content
echo "<p>Clatu, verata, nicto</p>";
// end secure content
} // end if ( verify() )
?>
</body>
</html>
End Ex. 2
As I said, this is just a frame-work. I like to start all my projects
this way. It allows me to get a grand view of what I'm doing before
getting mired down in the details.
Basically, so far, all we've done is place some secret content
inside an if statement. If the user is valid, we show the content,
if not, we don't. Writing a log-in form
The first thing we should flesh out is our log-in function. This
is a basic form, with no bells and whistles, so it should be pretty
straight forward.
Ex 3
function write_log_in( $text )
{
echo "
<p>$text</p>
<form method='post' action=''>
<p>User ID: <input type='text' name='user_name /></p>
<p>Password: <input type='password' name='password' /></p>
<p><input type='submit' value='Log In'></p>
</form>
";
} // end write_log_in function
End Ex. 3
No problems, right? All this is is PHP writing a basic HTML log-in
form. Two things are worth noting:
1. The method attribute to the <form> tag is 'post'. We could
have used 'get', but that would add our user name and password to
the URL as varibles. ie our_url?user_name=bob&password=truck64
. This shows the password--in plain text-- right there in the URL.
Why spend all this time on security if you're just going to put
peoples' passwords out for display?
'post' is much more secure, forcing the server to keep track of
form data, rather that the URL. Any time you can keep information
out of the URL, you're one step closer to a secure web page.
2. Next you want to look at the action attribute to the <form>
tag. Leaving it blank tells the server that you plan to process
these form results with this same page.
Checking the log-in values
Now let's flesh out our frame-work a little more.
Ex. 4
<?php
// start session if not already started
session_start();
// check to see if user just logged out
if ( $log_out )
{
}
function write_log_in( $text )
{
} // end write_log_in function
function verify()
{
// check to see if they're already logged in
// if yes, return true
// check to see if visitor has just tried to log on
$user_name = $_POST["user_name"];
$password = $_POST["password"];
if ( $user_name && $password )
{
// verify password and log in to database
$db = mysql_pconnect( "localhost", "$user_name",
"$password" );
if ( $db )
{
// register session variable and exit the verify function
$valid_user = $user_name;
$_SESSION['valid_user'] = $valid_user;
return true;
}
else
{
// bad user and password
$text = "User Name and Password did not match";
write_log_in( $text );
}
}
else
{
// if the user didn't just log-in, (s)he needs to
}
} // end verify function
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://
www.w3.org/ TR/ xhtml1/ DTD/ xhtml1-strict.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml"" xml:lang="en"
lang="en">
<head><title>Dan McConkey's Free Web Marketing Guide</title></head>
<body>
<p>Dan McConkey's Free Web Marketing Guide</p>
<?php
// check for valid user
if ( verify() )
{
// begin secure content
echo "<p>Clatu, verata, nicto</p>";
// end secure content
} // end if ( verify() )
?>
</body>
</html>
End Ex. 4
First, we'll check whether the user has just tried to log in.
$_POST is a PHP superglobal array that keeps track of data sent
to a page via a <form method='post'> tag. In the log-in function,
we named our inputs user_name and password, so we can access the
user input by calling $_POST["user_name"] and $_POST["password"].
We next run an if ( $user_name && $password ) statement
to see if both $_POST["user_name"] and $_POST["password"]
hold values. If they do, the user just tried to log in.
Our next section of code is the part that actually checks whether
the user name and password are correct. Here, we use MySQL's User
table (part of the mysql database) to keep track of our users. This
is, perhaps, the best route, as MySQL is already set up to control
access permissions. However, this can present problems when you
want to keep the database connection open across pages. Also, some
hosting companies won't give you grant access (let you make new
users) to the mysql database.
In those cases, you can accomplish much the same thing by setting
up your own users table in your database. You would then need to
write an SQL query that compares user names and passwords. That
would look something like this:
Ex. 5
$select = "select user_name from users
where user_name='$user_name'
and password=PASSWORD( '$password' )";
$query = mysql_query( $select );
if ( mysql_num_rows( $query ) == 1 )
{
// validated user and password
...
End Ex 5
Getting back to our validation using MySQL's built in features,
we know that the user name and password checked out because the
connection attempt returned true.
Registering a session variable
Now that we know our user name and password check out, we need
to store that information and allow our user to continue surfing
our protected area without logging in each and every page. Looking
back at example four, we notice another of PHP's superglobal variables:
$_SESSION.
$_SESSION is an array that holds all of our session variables.
By setting the valid_user session variable, we can later make a
call to ession_is_registered( "valid_user" ) to see if
our user has already logged in successfully.
Logging out
The last thing we have to attend to is allowing our users to log
out of our system. In this case, we've used a simple link inside
our protected area.
Ex 6
<?php
// start session if not already started
session_start();
// check to see if user just logged out
if ( $log_out )
{
session_unregister( "valid_user" );
session_destroy();
session_start();
}
function write_log_in( $text )
{
} // end write_log_in function
function verify()
{
} // end verify function
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://
www.w3.org/ TR/ xhtml1/ DTD/ xhtml1-strict.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml"" xml:lang="en"
lang="en">
<head><title>Dan McConkey's Free Web Marketing Guide</title></head>
<body>
<p>Dan McConkey's Free Web Marketing Guide</p>
<?php
// check for valid user
if ( verify() )
{
echo "<p><a href='?log_out=1'>Log out</a></p>";
// begin secure content
echo "<p>Clatu, verata, nicto</p>";
...
End Ex 6
First, looking in the HTML body, we see a simple HTML link that
adds a variable to the URL. In this case, the variable name is log_out
and its value is 1. We use 1 as a value because it's easy to store
in a URL, but really any value greater than zero will work.
Once we pass a log-out request to the page, we need to process
it. That's what the if( $log_out) part is for.
The if statement checks if a log-out request was passed. Once it
sees that one was, it unregisters the valid_user session variable,
then it destroys the session entirely.
Ironically, it starts a new session right back up. That's in case
the user decides to log in later (without closing the browser window),
or log in as a different user. The final code
Putting it all together we get this:
Ex. 7
<?php
// start session if not already started
session_start();
// check to see if user just logged out
if ( $log_out )
{
session_unregister( "valid_user" );
session_destroy();
session_start();
}
function write_log_in( $text )
{
echo "
<p>$text</p>
<form method='post' action=''>
<p>User ID: <input type='text' name='user_name /></p>
<p>Password: <input type='password' name='password' /></p>
<p><input type='submit' value='Log In'></p>
</form>
";
} // end write_log_in function
function verify()
{
// check to see if they're already logged in
if ( session_is_registered( "valid_user" ) ) return true;
// check to see if visitor has just tried to log on
$user_name = $_POST["user_name"];
$password = $_POST["password"];
if ( $user_name && $password )
{
// verify password and log in to database
$db = mysql_pconnect( "localhost", "$user_name",
"$password" );
if ( $db )
{
// register session variable and exit the verify function
$valid_user = $user_name;
$_SESSION['valid_user'] = $valid_user;
return true;
}
else
{
// bad user and password
$text = "User Name and Password did not match";
write_log_in( $text );
}
}
else
{
// user must log in
$text = "This is a secure server. Please log in.";
write_log_in( $text );
}
} // end verify function
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://
www.w3.org/ TR/ xhtml1/ DTD/ xhtml1-strict.dtd'>
<html xmlns="http://www.w3.org/1999/xhtml"" xml:lang="en"
lang="en">
<head><title>Dan McConkey's Free Web Marketing Guide</title></head>
<body>
<p>Dan McConkey's Free Web Marketing Guide</p>
<?php
// check for valid user
if ( verify() )
{
echo "<p><a href='?log_out=1'>Log out</a></p>";
// begin secure content
echo "<p>Clatu, verata, nicto</p>";
// end secure content
} // end if ( verify() )
?>
</body>
</html>
End Ex. 7
That's a pretty hefty code block to put at the head of every web
page. Typically, I would put my verify() and write_log_in()functions
into a seperate file and reference them with an include() function.
That provides the added benifit of updating your entire website
by editing one file only. Hope that helps.
Copyright (C) 2005 Dan McConkey
About The Author
Dan McConkey is a freelance web marketing professional,
working in and around Charlotte, NC. In the web, Dan has found an
amazing potential for lead generation for businesses. Using traditional
advertising theories, appropriate technologies, and a little common
sense, your electronic marketing campaigns can easily be your most
effective.
Dan maintains Dan McConkey's Free Web Marketing Guide at http://www.dmcconkey.com
dmcconkey@yahoo.com
Return to
the Resources Archive
|