Article

The PHP Anthology Volume 2, Chapter 1 - Access Control

Page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Next

New Password

As I mentioned, if you've encrypted the password, you have a different problem to solve. PHP's md5 function provides one-way encryption; once it's scrambled, there's no getting it back! In such cases, if members forget their passwords, you'll have to make new ones for them. You could simply generate a random string of characters, but it's important to remember that if you make your security systems too unfriendly, you'll put legitimate users off.

Here, we'll add to the AccountMaintenance class some further methods that can generate passwords, and subsequently modify the password stored in the database. I've used a list of 1370 words, stored in a text file, to build the memorable passwords. Be aware that if anyone knows the list of words you're using, cracking the new password will be significantly easier, so you should create your own list. First, let's look at the new class methods:

Example 1.37. AccessControl/AccountMaintenance.php (in SPLIB) (excerpt)            
           
 /**            
  * Given a username / email combination, resets the password            
  * for that user and returns the new password.            
  * @param string login name            
  * @param string email address            
  * @return array of user details or FALSE if failed            
  * @access public            
  */            
 function resetPassword($login, $email)            
 {            
   $login = mysql_escape_string($login);            
   $email = mysql_escape_string($email);            
   $sql = "SELECT " . USER_TABLE_ID . ",            
             " . USER_TABLE_LOGIN . ", " . USER_TABLE_PASSW . ",            
             " . USER_TABLE_FIRST . ", " . USER_TABLE_LAST . "            
           FROM            
             " . USER_TABLE . "            
           WHERE            
             " . USER_TABLE_LOGIN . "='$login'            
           AND            
             " . USER_TABLE_EMAIL . "='$email'";            
   $result = $this->db->query($sql);            
   if ($result->size() == 1) {            
     $row = $result->fetch();            
     if ($password = $this->generatePassword()) {            
       $sql = "UPDATE " . USER_TABLE . "            
               SET            
               " . USER_TABLE_PASSW . "='" . md5($password) . "'            
               WHERE            
               " . USER_TABLE_ID . "='" . $row[USER_TABLE_ID] .            
               "'";            
       $result = $this->dbConn->fetch($sql);            
       if (!$result->isError()) {            
         $row[USER_TABLE_PASSW] = $password;            
         return $row;            
       } else {            
         return FALSE;            
       }            
     } else {            
       return FALSE;            
     }            
   } else {            
     return FALSE;            
   }            
 }

The resetPassword method, when given a combination of a login and an email address, identifies the corresponding row in the user table, and calls the generatePassword method (which we'll discuss in a moment) to create a new password. It then updates the user table with the new password (using md5 to encrypt it), and returns the new password in an array containing the user details. If you're using a different table structure, you'll need to modify this method.

Note that we use both the login and email to identify the row, so it's a little more difficult for other people to reset your members' passwords. Although there's no risk in individuals stealing the new password (unless they have control over a member's email account), it will certainly irritate people if their password was being continually reset. Requiring both the login name and email of the user makes it a little more complex.

Of the next two methods, addWords is used to supply the class with an indexed array of words with which to build memorable passwords, while generatePassword constructs a random password from this list, adding "separators" that could be any number from 0 to 9, or an underscore character. The password itself will contain two words chosen at random from the list, as well as two random separators. The order in which these elements appear in the password is also random. The passwords this system generates look like "7correct9computer" and "48courtclothes," which are relatively easy for users to remember.

Example 1.38. AccessControl/AccountMaintenance.php (in SPLIB) (excerpt)            
           
 /**            
  * Add a list of words to generate passwords with            
  * @param array            
  * @return void            
  * @access public            
  */            
 function addWords($words)            
 {            
   $this->words = $words;            
 }            
           
 /**            
  * Generates a random but memorable password            
  * @return string the password            
  * @access private            
  */            
 function generatePassword()            
 {            
   srand((double)microtime() * 1000000);            
   $seperators = range(0,9);            
   $seperators[] = '_';            
   $count = count($this->words);            
   if ($count == 0) {            
     return FALSE;            
   }            
   $password = array();            
   for ($i = 0; $i < 4; $i++) {            
     if ($i % 2 == 0) {            
       shuffle($this->words);            
       $password[$i] = trim($this->words[0]);            
     } else {            
       shuffle($seperators);            
       $password[$i] = $seperators[0];            
     }            
   }            
   shuffle($password);            
   return implode('', $password);            
 }

First, we add to the form a new field for the user to enter their login name:

Example 1.39. 10.php (excerpt)            
           
// Add a field for the login            
$form->addElement('text', 'login', 'Enter your login name');            
$form->addRule('login', 'Enter your login', 'required', FALSE,            
              'client');

All that's required now is a small modification to the process that occurs upon the form's submission:

Example 1.40. 10.php (excerpt)            
           
// If the form is submitted...            
if ($form->validate()) {            
             
 // Instantiate MySQL connection            
 $db = &new MySQL($host, $dbUser, $dbPass, $dbName);            
             
 // Instantiate Account Maintenance class            
 $aMaint = new AccountMaintenance($db);            
             
 // Fetch a list of words            
 $fp = fopen('./pass_words/pass_words.txt', 'rb');            
 $file = fread($fp, filesize('./pass_words/pass_words.txt'));            
 fclose($fp);            
             
 // Add the words to the class            
 $aMaint->addWords(explode("\n", $file));            
             
 // Reset the password            
 if (!$details = $aMaint->resetPassword(            
       $form->getSubmitValue('login'),            
       $form->getSubmitValue('email'))) {            
   echo 'We have no record of your account';            
 } else {            
   // Instantiate phpmailer class            
   $mail = new phpmailer();            
   …

This time, we read a file (refer to Chapter 4, Files for details on this process) to obtain a list of words, the file having one word per line. We pass the list of words to the AccountMaintenance class with the addWords method. Whether you choose to use a file, a database or even some cunning code mechanism based upon the pspell_suggest function (see the PHP Manual) is up to you; you simply need to provide a list to add with addWords.

The resetPassword method changes the password behind the scenes and returns an array containing the user details in the same way as the fetchPassword method; thus, the task of emailing users their new passwords is the same. The code is therefore omitted from the above listing.

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links