Effortless E-Commerce with PHP and MySQL: User Accounts
- Protecting Passwords
- Registration
- Logging In
- Logging Out
- Managing Passwords
- Improving the Security
The next step in the evolution of the âKnowledge Is Powerâ e-commerce site is to create a system of user accounts. When the site is complete, PayPal will be the crucial part in the registration process, but just to understand the user account system on its own, as well as to be able to create an administrative user for the next chapter, letâs look at user accounts as a separate entity first.
There are four primary facets to the implementation of user accounts in this chapter. First, a new user registers. Second, a registered user logs in. Third, the logged-in user logs out (in theory, many people, including me, donât always do so). Fourth, users need to be able to retrieve a forgotten password and change an existing password.
Although this example wonât be storing any sensitive e-commerce data, security will still be taken seriously, for the benefit of the customers and the site itself. In a few places, Iâll make recommendations as to how you can increase security even further, and the chapter ends with even more suggestions. Chapter 12, âExtending the First Site,â makes even more suggestionsâsecurity-related and otherwise.
Protecting Passwords
How secure a user account system is will depend largely on how passwords are handled. Passwords can be stored on the server in three ways:
- In plain text, which is a terrible thing to do
- In an encrypted format, which can be decrypted
- In a hashed format, which canât be decrypted
If you store passwords in an encrypted format, itâs safe from prying eyes and can be retrieved when necessary. But if someone gets onto your server and can find your code for performing the decryption, that person will be able to view every userâs password. And it turns out that you donât need passwords to be decryptable: It doesnât matter whether or not anyone can ever see the plain text in its original form again.
An alternative is to create a hash of the password. A hash is a representation of data. For example, MD5 is a hashing algorithm thatâs been around for years. The MD5 hash of the word âpasswordâ is 5f4dcc3b5aa765d61d8327deb882cf99; the MD5 hash of the word âomnivoreâ is 04f7696e917f292f99925f80fcdb1db1. You can create a hash out of any piece of data, and, in theory, no two pieces of data have the same hash.
Storing the hash version of a password is more secure in that it canât be decrypted. If hackers get your data, the best they can do is create hashes of common words in the hopes that they find the matching hash (this is called a dictionary attack). But storing a hash still makes logging in possible: When a user logs in, the hashed version of the userâs login password just needs to equal the already stored hashed version. If the two hashes equate, the submitted password is correct.
Once youâve decided to hash the passwords, youâll need to choose what hashing algorithm (or formula) to use and where the hashing should take place. By the latter I mean that you can hash the password in either the database or in your PHP code. Normally I recommend having the database do as much as possible, but PHP has more sophisticated hashing functions available than MySQL.
MD5 is a common legacy hashing algorithm, but not very secure. An improvement is SHA or SHA1, which are fine for some applications, although not e-commerce. For improved security, Iâm going to turn to PHPâs very new password_hash() function. This function was added to the language as of PHP 5.5. This means you must have a current version of PHP in order to use it (as of this writing, the most current version is only 5.5.3).
If you arenât running PHP 5.5 or greater, you can use an external library found at https://github.com/ircmaxell/password_compat. This library was created by Anthony Ferrara (http://blog.ircmaxell.com/) and is the basis for the version implemented in PHP 5.5. The library requires PHP 5.3.7 or greater.
To test whether you can use the library:
- Download the zip file from the GitHub URL just mentioned.
Unzip the downloaded file to create a folder of goodies (Figure 4.1).
- Copy the version-test.php file to your serverâs web directory.
- Run the version-test.php in your browser (Figure 4.2).
Figure 4.2
If youâre not using PHP 5.5 or greater, and if the password_compat library indicates that it canât be used, you should upgrade your PHP version. If thatâs not possible either, post a message in my support forums (www.LarryUllman.com/forums/) for alternative hashing approaches.
To hash passwords with this new function, youâll use this code:
$hash = password_hash($password, PASSWORD_BCRYPT);
That will work if you have PHP 5.5 or later. If youâre using the password_compat library, you must first include that library. Copy the lib directory from the downloaded file (see Figure 4.1) into your includes folder. Then include the library prior to invoking password_hash():
include('./includes/lib/password.php'); $hash = password_hash($password, PASSWORD_BCRYPT);
Thatâs all there is to it! Itâs very simple and yet highly secure.
To verify a password upon login, use the password_verify() function. Its first argument is the submitted, unhashed password. The second is the stored, hashed password:
if (password_verify($password, $hash)) { /* Valid */ } else { /* Invalid */ }
Again, if youâre using the password_compat library youâll need to include it prior to calling password_verify().