Passwords Don’t Belong in PHP Scripts PHP Help

Databases are better for storing passwords because, among other reasons, they’re typically more difficult to access than your scripts, which are to some degree web accessible. Your database, on the other hand, is generally at least a layer further removed from the typical web user. Additionally, your database and SOL require structural knowledge to be useful. Scripts are just files that can be browsed, and often the information in those files is just text. Clearly, a database is a safer place for passwords than authorize.php.

There’s yet another reason to place your passwords into a database: You’re already storing user information there. You can connect that information to a password by adding a column. Moreover, as you’ll see soon, groups of users aren’t far away, either. Before you get too comfortable, though, you need to dig back into MySQL and improve that authentication situation.’

Updating the users Table
The first thing you need to do is update users. It’s been a while since you’ve been poking around in there, so here’s a refresher as to what you should have at this point.

Updating the users Table

There’s nothing wrong here, but there are some omissions: notably a user name and a password. Those are the two essential pieces of information that your basic authentication requires.

Use the following to add two columns to your table:

mysql> ALTER TABLE users
-> ADD username VARCHAR(32) NOT NULL
-> AFTER user_id,
-> ADD password VARCHAR(16) NOT NULL
-> AFTER username;

Take a moment to verify that these changes are in place now:’

Updating the users Table

Dealing with Newly Invalid Data

As was the case-when you added columns before, you now have a table full of invalid rows. Because both user name and password are required (NOT NULL), and none of the existing rows have values in those columns, all of your table’s rows are in violation of that table’s rules.

You can fix this by using some more SQL. For example, to update Jason Wadley, you’d use something like this:

mysql> UPDATE users
-> SET username = “jwadley”,
-> password = ” chung_moo”
-> WHERE user_id = 21;

You can confirm that these changes were made, as well:

Dealing with Newly Invalid DataYou should make similar changes to your own users table so all the users you’ve added have a user name and password.

What’s in a (User) Name?

It seems like every time you turn around, a new social website is popping up-a site that you simply. More and more of those sites are using email addresses as your login name. There’s a lot to like about this approach:

• Most people remember their email address more readily than one of 50 different user names floating around.

• Email addresses like [email protected] are a lot more readable (and typeable) than a user name like tn1954a.

• It’s one less piece of information to store in your database. So, if that’s the way the wind is blowing, why create a user name column in users Why not just use the email address?

First. a lot of people have just as many email addresses as they have user names these days. With GMail, Apple’s iCloud, at least one business email, and perhaps a personal domain or two, individuals can still have a hard time remembering which email address to use for login.

Second, plenty of people don’t like using their email addresses as their user name. A user name seems more anonymous, whereas your email address is a way to get something into your inbox. It might seem odd, but lots of people are fine with supplying an email as part of signup, but they’re not comfortable typing it into a lot of login boxes.

Perhaps the most important reason is that, if an email is the user name, how do you retrieve a user’s password? Typically, with a user name system, you require a user to supply his user name when a password is lost as some sort of verification. When the user’s email his user name, you need to come up with a different method of verification.

Even though there’s nothing wrong with using an email address, it’s still a bit better to require a dedicated user name. Besides, fantastic programs like Password (www.phphelponline.com) make it easy for your users (and you) to manage multiple log ins. (Seriously, although it might seem a bit pricey at $59.99, go buy 1Password today. It’s a web-life changer.)

Getting an Initial User Name and Password

At this juncture, you’ve got to go back …way back. Remember create_users.php? That was the rather simple HTML form that gathers the user’s initial information. To be able to go forward, it needs some improvement: a user name and password field, for starters.

Here’s a significantly updated version of create user.html, which adds-among a lot of other things-a field in which new users can enter a user name and two fields that combine to get a password.

Getting an Initial User Name and Password

In addition to the two new fields, this version of the form adds in some jQuery, which is available from http://www.phphelponline.com free, downloadable JavaScript library that makes almost everything in JavaScript a lot easier, In addition to the core jQuery library, there are two jQuery plug-ins, which you can see near the top of the code:

FIGURE 12-8

FIGURE 12-8

FIGURE 12-9

FIGURE 12-9

FIGURE 12-10

FIGURE 12-10

Now, you’re getting the right information from your users. It’s time to update your PHP to do something with this.

Inserting the User Name and Password

At this point, you can update create._’!ser ph.:, as well. This update is straightforward and certainly requires a lot less work, although the result of these changes is significant.

Inserting the User Name and Password

As usual, try entering some sample data and confirm that you get a normal show_users.php response as a validation that all your changes work. Also, ensure that you do not add authorize.php to your scripts list of require_once statements. You can hardly require users to log in to the form with which they tell your application about the user name and password they want to use for those logins.

There’s No One Quite Like You
Yes. You should put the book down and write that code, right now. In the current version of create_users.php are inserted into the database without checking whether their user names are unique. Certainly, you could enforce that at the database level, but then you’d just get a nasty error. In its simplest form, you could do a SELECT on the desired user name, and if any users are returned, redirect the user to an error page by using handle_error. That’s pretty primitive, though. It completely shuts down any flow, and the user-if she doesn’t bail from your application completely-will have to enter all of her information into the user Sign-in form again. A better approach would be to convert create_users.html a script, or even roll it into the current version of In either case, if the user name is already taken, the user should be redirected back to the sign-in form, with all her previous information filled in, and a message should tell her to try another user name. Then, if you want to move into the deep end of the pool, do everything above, but do it with Ajax so that the sign-in page never reloads.

So, where’s the code for this? It’s in your head and at your fingertips. At this stage of your PHP journey, you’re increasingly ready to tackle problems like this yourself. Usea book or the Web as a resource for new techniques-like authentication in this chapter or sessions in Chapter 14-but you’re plenty capable of working out new uses for things you already know on your own.

Connect authorize.php to Your users Table

At this point, there’s just one glaring hole to plug: authorize.php Right now, there is only one user name and one password accepted, and they’re here in this rather silly bit of constant work:

define(VALID _USERNAME, “admin”);
define(VALID_PASSWORD, “super_secret”);

Now, however,authorization has a users table from which to pull user names and passwords. Fortunately, fixing up eutncnze.ono requires simply stringing together things you’ve already done. First, remove those two constants and add in require_once for ceteosse; ccnnecuon.ono, which you’ll need for interacting with the users table.
<?php
require_once’database_connection.php’;
// define(VALID_USERNAME, “admin”); DELETE THIS LINE
// define(VALID_PASSWORD, “super_secret”); DELETE THIS LINE
if (lisset($_SERVER[‘PHP_AUTH_USER’]) //
lisset($_SERVER[‘PHP_AUTH_PW’]) //
($_SERVER[‘PHP_AUTH_USER’] 1= VALID_USERNAME) //
($_SERVER[‘PHP_AUTH_PW’] 1= VALID_PASSWORD» {
header(‘HTTP/1.1 401 Unauthorized’);
header(‘WWW-Authenticate: Basic realm=”The Social Site”‘);
exit(“You need a valid username and password to be here. ”
“Move along, nothing to see.”);
?>

That big, burly if statement needs to be trimmed some. The first portion still works; if the $_SERVERsuperglobal has no value for PHP_AUTH_USERor PHP_AUTH_PW headers should still be sent to the browser, instructing it to pop up a login dialog box. But now, there’s no VALID_USERNAMEor VALID_PASSWORDconstant to which the user’s values should be compared, so that part of the if statement has to go. Here’s what should be left:

if (lisset($_SERVER[‘PHP_AUTH_USER’]) //
lisset($_SERVER[‘PHP_AUTH_PW’]» {
header(‘HTTP/1.1 401 Unauthorized’);
header(‘WWW-Authenticate: Basic realm=”The Social Site”‘);
exit(“You need a valid username and password to be here. ”
“Move along, nothing to see.”);

The next thing the script needs to do is to get anything the user entered-and if the script gets this far, the user did enter something-and compare it to values in the database. This is something you’ve done a number of times. It’s just more sprintf and mysql_real_escape_string, both of which you’ve used before:

Connect authorize.php to Your users Table

There’s nothing particularly new here; you know how to get the results. But this time, before worrying about the actual values from the response, the biggest concern is seeing whether there ere any results. If a row matches the user name and password provided, the user is legitimate. (Or, he’s borrowed someone else’s credentials. And “borrowed” is being used loosely here.)

The first thing to do is to see whether there are any results. If there are none, the script has reached the same point as the earlier version, when the user name and password weren’t valid. This means sending those headers again:

if (mysql_num_rows($results) == 1) {
II Everything’s ok! Let this user through
} else {
header(‘HTTP/1.1 401 Unauthorized’);
header(‘WWW-Authenticate: Basic realm=”The Social Site”‘);
exit(“you need a valid username and password to be here. ”
“Move along, nothing to see.”);

There’s just one more thing to do, and it’s a bit of a nicety. Because the user has just logged in, go ahead and let any script that calls authorize.php have access to that newly logged-in user:

if (mysql_num_rows($results) == 1) {
$result = mysql_fetch_array($results);
$current_user_id = $result[‘user_id’];
$current_username = $result[‘username’];
} else {
header(‘HTTP/1.1 401 Unauthorized’);
header(‘WWW-Authenticate: Basic realm=”The Social Site”‘);
exit(“you need a valid username and password to be here. ”
“Move along, nothing to see.”);

The entire script, new and certainly improved, looks like this:

<?php
require_once ‘database_connection.php’j
if (lisset($_SERVER[‘PHP_AUTH_USER’]) //
lisset($_SERVER[‘PHP_AUTH_PW’])) {
header(‘HTTP/1.1 401 Unauthorized’);
header(‘WWW-Authenticate: Basic realm=”The Social Site”‘);
exit(“you need a valid username and password to be here. ”
“Move along, nothing to see.”);
II Look up the user-provided credentials
$query = sprintf(“SELECT user_id, username FROM users ”
” WHERE username = ‘%s’ AND” .
password = ‘%5’;”,
mysql_real_escape_string(trim($_SERVER[‘PHP_AUTH_USER’])),
mysql_real_escape_string(trim($_SERVER[‘PHP_AUTH_PW’])));
$results = mysql_query($query);
if (mysql_num_rows($results) 1) {
$result ~ mysql_fetch_array($results);
$current_user_id ~ $result[‘user_id’];
$current_username ~ $result[‘username’];
} else {
header(‘HTTP/1.1 401 Unauthorized’);
header(MW-Authenticate: Basic realm~”The Social Site”‘);
exit(“you need a valid username and password to be here. ”
“Move along, nothing to see.”);

Test it out. Create a user (or add a user name and password to an existing user in your database), and then close and re-open your browser to reset any saved credentials. Go to show_users.php or any other page in which you’ve required authorize.php. You should get a login dialog box, be able to enter database values, and see the page you requested.

Posted on January 12, 2016 in Authentication and Authorization

Share the Story

Back to Top
Share This