Recipe 18.8. Dealing with Lost Passwords


18.8.1. Problem

You want to issue a password to a user who has lost her password.

18.8.2. Solution

Generate a new password and send it to the user's email address (which you should have on file):

<?php /* Generate new password. */ $new_password = ''; for ($i = 0; $i < 8; $i++) {     $new_password .= chr(mt_rand(33, 126)); } /* Define a salt. */ define('SALT', 'flyingturtle'); /* Encrypt new password. */ $encrypted_password = md5(SALT . $new_password); /* Save new encrypted password to the database. */ $st = $db->prepare('UPDATE users             SET    password = ?             WHERE  username = ?'); $st->execute(array($encrypted_password, $clean['username'])); /* Email new plain text password to user. */ mail($clean['email'], 'New Password', "Your new password is: $new_password"); ?> 

18.8.3. Discussion

If a user forgets her password, and you store encrypted passwords as recommended in Recipe 18.7, you can't provide the forgotten password. The one-way nature of md5( ) prevents you from retrieving the plain-text password.

Instead, generate a new password and send that to her email address. If you send the new password to an address you don't already have on file for that user, you don't have a way to verify that the new address really belongs to the user. It may be an attacker attempting to impersonate the real user.

Because the email containing the new password isn't encrypted, the code in the Solution doesn't include the username in the email message to reduce the chances that an attacker that eavesdrops on the email message can steal the password. To avoid disclosing a new password by email at all, let a user authenticate herself without a password by answering one or more personal questions (the answers to which you have on file). These questions can be "What was the name of your first pet?" or "What's your mother's maiden name?"'anything a malicious attacker is unlikely to know. If the user provides the correct answers to your questions, you can let her choose a new password.

One way to compromise between security and readability is to generate a password for a user out of actual words interrupted by some numbers:

<?php $words = array('mother', 'basset', 'detain', 'sudden', 'fellow', 'logged',                'remove', 'snails', 'direct', 'serves', 'daring', 'chirps',                'reward', 'snakes', 'uphold', 'wiring', 'nurses', 'regent',                'ornate', 'dogmas', 'mended', 'hinges', 'verbal', 'grimes',                'ritual', 'drying', 'chests', 'newark', 'winged', 'hobbit'); $word_count = count($words); $password = sprintf('%s%02d%s',                     $words[mt_rand(0,$word_count - 1)],                     mt_rand(0,99),                     $words[mt_rand(0,$word_count - 1)]); echo $password; ?> 

This code produces passwords that are two six-letter words with two numbers between them, like mother43hobbit or verbal68nurses. The passwords are long, but remembering them is made easier by the words in them.

18.8.4. See Also

Recipe 18.7 for information about storing encrypted passwords.




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net