// to make it a slightly better password srand double microtime * 1000000; $rand_number = rand0, 999; $new_password .= $rand_number; // set user's password to this in database or return
Trang 1// to make it a slightly better password srand ((double) microtime() * 1000000);
$rand_number = rand(0, 999);
$new_password = $rand_number;
// set user's password to this in database or return false
if (!($conn = db_connect())) return false;
$result = mysql_query( "update user
set passwd = password('$new_password') where username = '$username'");
if (!$result) return false; // not changed else
return $new_password; // changed successfully }
This function generates its random password by getting a random word from a diction-ary, using the get_random_word()function and suffixing it with a random number between 0 and 999.The get_random_word()function is also in the user_auth_fns.php library.This function is shown in Listing 24.19
Listing 24.19 The get_random_word() Function from user_auth_fns.php—This
Function Gets a Random Word from the Dictionary for Use in Generating Passwords
function get_random_word($min_length, $max_length) // grab a random word from dictionary between the two lengths // and return it
{ // generate a random word
$word = '';
//remember to change this path to suit your system
$dictionary = '/usr/dict/words'; // the ispell dictionary
$fp = fopen($dictionary, 'r');
if(!$fp) return false;
$size = filesize($dictionary);
// go to a random location in dictionary srand ((double) microtime() * 1000000);
$rand_location = rand(0, $size);
fseek($fp, $rand_location);
// get the next whole word of the right length in the file while (strlen($word)< $min_length || strlen($word)>$max_length Listing 24.18 Continued
Trang 2498 Chapter 24 Building User Authentication and Personalization
{
if (feof($fp)) fseek($fp, 0); // if at end, go to start
$word = fgets($fp, 80); // skip first word as it could be partial
$word = fgets($fp, 80); // the potential password };
$word=trim($word); // trim the trailing \n from fgets return $word;
}
To work, this function needs a dictionary If you are using a UNIX system, the built-in spell checker ispell comes with a dictionary of words, typically located at
/usr/dict/words, as it is here, or at /usr/share/dict/words If you don’t find it in one of these places, on most systems you will be able to find yours by typing locate dict/words
If you are using some other system or do not want to install ispell, don’t worry! You can download word lists as used by ispell from
http://wordlist.sourceforge.net/
This site also has dictionaries in many other languages, so if you would like a random, say, Norwegian or Esperanto word, you can download one of those dictionaries instead These files are formatted with each word on a separate line, separated by newlines
To get a random word from this file, we pick a random location between 0 and the filesize, and read from the file there If we read from the random location to the next newline, we will most likely only get a partial word, so we skip the line we open the file
to, and take the next word as our word by calling fgets()twice
The function has two clever bits.The first is that, if we reach the end of the file while looking for a word, we go back to the beginning:
if (feof($fp)) fseek($fp, 0); // if at end, go to start
The second is that we can seek for a word of a particular length—we check each word that we pull from the dictionary, and, if it is not between $min_lengthand
$max_length, we keep searching At the same time, we also dump words with apostro-phes (single quotes) in them.We could escape these out when using the word, but it is easier to just get the next word
Back in reset_password(), after we have generated a new password, we update the database to reflect this, and return the new password back to the main script.This will then be passed on to notify_password(), which will email it to the user
Let’s have a look at the notify_password()function, shown in Listing 24.20 Listing 24.19 Continued
Trang 3Listing 24.20 The notify_password() Function from user_auth_fns.php—This Function
Emails a Reset Password to a User
function notify_password($username, $password) // notify the user that their password has been changed {
if (!($conn = db_connect())) return false;
$result = mysql_query("select email from user
where username='$username'");
if (!$result) {
return false; // not changed }
else if (mysql_num_rows($result)==0) {
return false; // username not in db }
else {
$email = mysql_result($result, 0, 'email');
$from = "From: support@phpbookmark \r\n";
$mesg = "Your PHPBookmark password has been changed to $password \r\n"
."Please change it next time you log in \r\n";
if (mail($email, 'PHPBookmark login information', $mesg, $from)) return true;
else return false;
} }
In this function, given a username and new password, we simply look up the email address for that user in the database, and use PHP’s mail()function to send it to her
It would be more secure to give users a truly random password—made from any combination of upper and lowercase letters, numbers, and punctuation—rather than our random word and number However, a password like ‘zigzag487’ will be easier for our user to read and type than a truly random one It is often confusing for users to work out whether a character in a random string is 0 or O (zero or capital O), or 1 or l (one
or a lowercase L)
On our system, the dictionary file contains about 45,000 words If a cracker knew how we were creating passwords, and knew a user’s name, he would still have to try 22,500,000 passwords on average to guess one.This level of security seems adequate for this type of application even if our users disregard the emailed advice to change it
Trang 4500 Chapter 24 Building User Authentication and Personalization
Implementing Bookmark Storage and Retrieval
Now we’ll move on and look at how a user’s bookmarks are stored, retrieved, and deleted
Adding Bookmarks
Users can add bookmarks by clicking on the Add BM link in the user menu This will take them to the form shown in Figure 24.9
Figure 24.9 The add_bm_form.php script supplies a form where users can add bookmarks to their bookmark pages.
Again, this script is simple and uses just the output functions, so we will not go through
it here.When the form is submitted, it calls the add_bms.phpscript, which is shown in Listing 24.21
Listing 24.21 add_bms.php—This Script Adds New Bookmarks to a User’s Personal
Page
<?php require_once('bookmark_fns.php');
session_start();
//create short variable name
$new_url = $HTTP_POST_VARS['new_url'];
do_html_header('Adding bookmarks');
Trang 5if (!filled_out($HTTP_POST_VARS)) {
echo 'You have not filled out the form completely.
Please try again.';
display_user_menu();
do_html_footer();
exit;
} else { // check URL format
if (strstr($new_url, 'http://')===false)
$new_url = 'http://'.$new_url;
// check URL is valid
if (@fopen($new_url, 'r')) {
// try to add bm
if (add_bm($new_url)) echo 'Bookmark added.';
else echo 'Could not add bookmark.';
} else echo 'Not a valid URL.';
}
// get the bookmarks this user has saved
if ($url_array = get_user_urls($HTTP_SESSION_VARS['valid_user']));
display_user_urls($url_array);
display_user_menu();
do_html_footer();
?>
Again this script follows the pattern of validation, database entry, and output
To validate, we first check whether the user has filled out the form using filled_out()
We then perform two URL checks First, using strstr(), we see whether the URL begins with http:// If it doesn’t, we add this to the start of the URL After we’ve done this, we can actually check that the URL really exists As you might recall from Chapter
17, “Using Network and Protocol Functions,” we can use fopen()to open an URL that starts with http:// If we can open this file, we assume the URL is valid and call the function add_bm()to add it to the database
Listing 24.21 Continued