Page 1 of 1

Password Reset System Without Using A Database Rate Topic: -----

#1 Master Jake  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 16
  • View blog
  • Posts: 106
  • Joined: 27-February 09

Posted 20 October 2009 - 04:07 PM

NOTE: "Without Using A Database" means we aren't going to be storing keys in the database, not that we won't be using one period. We will need a database with user's in them; otherwise, resetting passwords is pretty pointless.

This tutorial is going to be on a password reset system to go with your registration/login systems. People forget their passwords often, so it is a good idea to create a system allowing them to reset their password when needed.

Now, there are a couple ways to go about doing this. One is without the use of a database, and one is with the use of a database. Obviously, we are going to be going over the one without the use of a database today.

The negative end of this is that each user's unique password reset key will always be the same. This being the case, this key should be protected even more than the password itself. I recommend telling the user's that when you e-mail them the key. If they are to give out their unique key to someone (as well as their e-mail address), anyone will be able to reset their account password at any time.

The positive end of actually using a database is the exact opposite of the negative end of not using one. When using a database, you can also generate a unique key for each user which is only good for one password recovery. This is much more secure as even if a user does give out his/her key, the password can only be reset once using that key. If a user's account is stolen, he/she can simply reset the password again which will send them a new unique key. They can use this new unique key to reset their password and then their account is safe again.

However, as stated, we aren't going to be using the database approach today.

Now, there are a few things this password reset system depends on:

1. PHP mail() function must be enabled
2. You must have each user's e-mail stored in a database in order for us to mail them their password

If you are ready, let's get started.

:)

First of all, we will use 2 pages for this complete system. I will only be posting the important snippets of each page such as the form and PHP script. We'll call these 2 pages forgot_password.php and reset_password.php

Let's start with forgot_password.php. We need to create a form which asks for the user's e-mail. The action of the form will be $_SERVER["PHP_SELF"] so that it returns to the same page the form is on to process the information. We will use PHP at the top of this page to process the form, create the unique user key, and then send it to them via e-mail.

Let's do the form first:
forgot_password.php
<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post">
E-mail Address: <input type="text" name="email" size="20" /> <input type="submit" name="ForgotPasswordForm" value=" Process " />
</form>



Alright. We have a text field called "email" and a submit button called "ForgotPasswordForm." The submit button is named so that we can check to see if the right form was submitted.

Now let's get onto the PHP code for this page:
forgot_password.php
<?php

// Connect to MySQL
$c = mysql_connect("localhost", "root", "");
mysql_select_db("main", $c);

// Was the form submitted?
if ($_POST["ForgotPasswordForm"])
{
	// Harvest submitted e-mail address
	$email = mysql_real_escape_string($_POST["email"]);

	// Check to see if a user exists with this e-mail
	$userExists = mysql_fetch_assoc(mysql_query("SELECT `email` FROM `users` WHERE `email` = '$email'"));
	if ($userExists["email"])
	{
				// Create a unique salt. This will never leave PHP unencrypted.
				$salt = "PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";

		// Create the unique user password reset key
		$password = md5($salt . $userExists["email"]));

		// Create a url which we will direct them to reset their password
		$pwrurl = "www.yoursite.com/reset_password.php?q=" . $password;

		// Mail them their key
		$mailbody = "Dear user,\n\nIf this e-mail does not apply to you please ignore it. It appears that you have requested a password reset at our website www.yoursitehere.com\n\nTo reset your password, please click the link below. If you cannot click it, please paste it into your web browser's address bar.\n\n" . $pwrurl . "\n\nThanks,\nThe Administration";
		mail($userExists["email"], "www.yoursitehere.com - Password Reset", $mailbody);
		echo "Your password recovery key has been sent to your e-mail address.";
	}
	else
		echo "No user with that e-mail address exists.";
}

?>



Quite a bit is going on here, so let's break it down into sections and I'll explain what each is doing.

<?php

// Connect to MySQL
$c = mysql_connect("localhost", "root", "");
mysql_select_db("main", $c);



We start by connecting to MySQL so that we can check to see if a user exists with the submitted e-mail, etc. The host, username, password, and database name may be different for your account. You should know your MySQL settings.

// Was the form submitted?
if ($_POST["ForgotPasswordForm"])
{



Here we are just checking to see if the form was submitted. If the post value of ForgotPasswordForm (the name of our form's submit button) is true, then the form was submitted.

// Harvest submitted e-mail address
$email = mysql_real_escape_string($_POST["email"]);



Here we are retrieving the e-mail submitted from the form and MySQL_Real escaping it. This is so that when we check it with the database, it won't contain harmful characters which can be used for SQL Injection. (Hackers are terrible people)

// Check to see if a user exists with this e-mail
$userExists = mysql_fetch_assoc(mysql_query("SELECT `email` FROM `users` WHERE `email` = '$email'"));
if ($userExists["email"])
{



These lines of code are interesting. We are creating a variable called "$userExists" which will actually become an associative array from mysql_fetch_assoc(). Basically, it is running a query saying, "Select the user's e-mail address from the table `users` where their e-mail address is equal to the one submitted."

Why are we doing this exactly? Well, to check to see if the user really does exists, of course. The fields in the query will change depending on your database, but I'm sure you already knew that. The next if statement checks to see if $userExists["email"] has a value. If it does, then we know the user exists (because the query returned a value into the variable).

// Create a unique salt. This will never leave PHP unencrypted.
$salt = "PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";



You may be wondering what this is. Well basically, it's a SALT. Now what is a SALT? It's a key of random letters, numbers, digits in general, characters, whatever you want to call it. It's basically a key that never leaves your PHP code. You do not store your salt in a database, print it to the screen, or ANYTHING without it being encrypted. It also needs to be long and very random so that it is very difficult to figure out what the salt really is when it is encrypted.

// Create the unique user password reset key
$password = md5($salt . $userExists["email"]));



This line makes use of the SALT. Basically we are saying, add the SALT together with the user's e-mail address and then hash it with MD5. If the user entered say "blahman@yahoo.com" for his e-mail address, the salt combined with that would become:

PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651blahman@yahoo.com

Now, when we hash this entire new combined string in MD5, it becomes secure. You will see later how we use this key to actually check and reset the password.

// Create a url which we will direct them to reset their password
$pwrurl = "http://www.yoursite.com/reset_password.php?q=" . $password;



Here we are creating a url and storing it in the variable "$pwurl." You don't have to store it into a variable and can actually put in the mail string itself, but I did this so it would be easier to point out and explain.

You basically need the URL to point your websites "reset_password.php" page that we talked about earlier in this tutorial. We are also adding "?q=" to the end of it and appending the user's new password key onto it. This way, we can check the URL on the "reset_password.php" page to get the user's key when they click the link from their e-mail.

// Mail them their key
$mailbody = "Dear user,\n\nIf this e-mail does not apply to you please ignore it. It appears that you have requested a password reset at our website www.yoursitehere.com\n\nTo reset your password, please click the link below. If you cannot click it, please paste it into your web browser's address bar.\n\n" . $pwrurl . "\n\nThanks,\nThe Administration";
mail($userExists["email"], "www.yoursitehere.com - Password Reset", $mailbody);
echo "Your password recovery key has been sent to your e-mail address.";



Here is the long message stored in the variable "$mailbody" which basically tells the user, "hey, if this is you, then click this link and reset your password." You will also see use of the "$pwrurl" variable inside the "$mailbody" string. That is the area where we are placing their password reset link we generated above. Finally, we are using mail() to actually send them the e-mail. We are using "www.yoursitehere.com - Password Reset" as the subject and the value of "$mailbody" as the body message.

}
else
	echo "No user with that e-mail address exists.";
}

?>



Here we are just cleaning up. The else refers to the if statement regarding whether or not the user actually exists. The last curly bracket closes the if statement regarding whether or not the form was actually submitted.

So, now we have created a page which asks the user for their e-mail address; and, if a user exists with that e-mail address, sends them an e-mail with a unique password recovery key for their account. Let's move on to the "reset_password.php" page.

This page is also going to have a form and some PHP code. First we will post the form which, once again, redirects to itself and then processes using PHP. In this form, we need the user to retype his/her e-mail address, new password, and confirm their new password. We also need to store the value of "?q=" from the URL into a hidden section of the form so we can carry it over into processing in post data.

reset_password.php
<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post">
E-mail Address: <input type="text" name="email" size="20" /><br />
New Password: <input type="password" name="password" size="20" /><br />
Confirm Password: <input type="password" name="confirmpassword" size="20" /><br />
<input type="hidden" name="q" value="<?php echo $_GET["q"]; ?>" /><input type="submit" name="ResetPasswordForm" value=" Reset Password " />
</form>



Now that we have the form for the page, let's move onto the PHP section.

reset_password.php
<?php

// Connect to MySQL
$c = mysql_connect("localhost", "root", "");
mysql_select_db("main", $c);

// Was the form submitted?
if ($_POST["ResetPasswordForm"])
{
	// Gather the post data
	$email = mysql_real_escape_string($_POST["email"]);
	$password = md5(mysql_real_escape_string($_POST["password"]));
	$confirmpassword = md5(mysql_real_escape_string($_POST["confirmpassword"]));
	$q = $_POST["q"];

	// Use the same salt from the forgot_password.php file
	$salt = "PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";

	// Generate the reset key
	$resetkey = md5($salt . $email);

	// Does the new reset key match the old one?
	if ($resetkey == $q)
	{
		if ($password == $confirmpassword)
		{
			// Update the user's password
			mysql_query("UPDATE `users` SET `password` = '$password' WHERE `email` = '$email'");
			echo "Your password has been successfully reset.";
		}
		else
			echo "Your password's do not match.";
	}
	else
		echo "Your password reset key is invalid.";
}

?>



Again, a lot is going on here. So let's break it down line by line.

<?php

// Connect to MySQL
$c = mysql_connect("localhost", "root", "");
mysql_select_db("main", $c);



Connecting to MySQL, again. Nothing new here.

// Was the form submitted?
if ($_POST["ResetPasswordForm"])
{



Checking to see if the form was submitted.

// Gather the post data
$email = mysql_real_escape_string($_POST["email"]);
$password = md5(mysql_real_escape_string($_POST["password"]));
$confirmpassword = md5(mysql_real_escape_string($_POST["confirmpassword"]));
$q = $_POST["q"];



This is gathering all of the post data submitted from the form and storing each value into a variable. You may notice the use of mysql_real_escape_string(). Again, we are using this to protect our database from SQL Injection. $q doesn't need to be escaped because we aren't going to be checking it with the database. Also, you may notice use of md5() on the password's. This is because I assume this is the hashing you are using on your passwords. Change it if needed.

// Use the same salt from the forgot_password.php file
$salt = "PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";



Here we are, once again, creating the salt. Make sure this is the EXACT same salt you used from the forgot_password.php file or the system won't work.

// Generate the reset key
$resetkey = md5($salt . $email);



As we did in the forgot_password.php file, we are combining the salt and the user's inputted e-mail and then hashing it with md5(). We are storing it into a variable called $resetkey this time.

// Does the new reset key match the old one?
if ($resetkey == $q)
{



This is the major check. Since we combined the same salt with the same e-mail and hashed it the same way, both $resetkey and $q will be the same. If they aren't the same, the user either inputted the wrong e-mail address or it's a hacker trying to steal their account.

if ($password == $confirmpassword)
{



This is making sure both the password and confirmed password match.

// Update the user's password
mysql_query("UPDATE `users` SET `password` = '$password' WHERE `email` = '$email'");
echo "Your password has been successfully reset.";



Here we are simply running a mysql_query() to update the user's password and set it to the new one where their e-mail equals the one submitted. Afterward, we are echoing out that it has been successful. Again, you may need to change the table `users` and the fields depending on your database.

}
else
	echo "Your password's do not match.";
}
else
	echo "Your password reset key is invalid.";
}

?>



This is all the clean up and finalizing code. We are running else statements on previous if's. The first one is for whether or not the password and confirmed password matched. If not, tell them it didn't. The second is for the check determining whether or not the new recovery key matched the old one. The final curly braces closes the if statement which checked to see if the form was actually submitted.

CONGRATULATIONS!

If you have made it this far, your password reset system is complete. I hope my tutorial has helped you learn and understand new concepts. Go out and enjoy the wonderful world of PHP now!

Is This A Good Question/Topic? 0
  • +

Replies To: Password Reset System Without Using A Database

#2 josh06  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 14
  • View blog
  • Posts: 139
  • Joined: 27-October 06

Posted 20 February 2010 - 05:51 AM

That is a really good system.
Thanks for the great tutorial.

I'll sure be using this!
Was This Post Helpful? 0
  • +
  • -

#3 jdbus9  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 15-March 13

Posted 15 March 2013 - 01:07 PM

So I am testing the password reset system on my test server and works for the most part but I do not receive a email.
This is what i get below What could be the problem any thoughts???


Your password recovery key has been sent to your e-mail address.
E-mail Address:



  <?php
	 
	// Connect to MySQL
	$c = mysql_connect("localhost", "root", "");
	mysql_select_db("", $c);
	 
	// Was the form submitted?
	if ($_POST["ForgotPasswordForm"])
	{
	    // Harvest submitted e-mail address
	    $email = mysql_real_escape_string($_POST["email"]);
	 
	    // Check to see if a user exists with this e-mail
	    $userExists = mysql_fetch_assoc(mysql_query("SELECT `email` FROM `signup` WHERE `email` = '$email'"));
	    if ($userExists["email"])
	    {
	                // Create a unique salt. This will never leave PHP unencrypted.
	                $salt = "PiuwrO1#O0rl@+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";
	 
	        // Create the unique user password reset key
	        $password = md5($salt . $userExists["email"]);
	 
	        // Create a url which we will direct them to reset their password
	        $pwrurl = "www.raceoclock.com/reset_password.php?q=" . $password;
	 
	        // Mail them their key
	        $mailbody = "Dear user,\n\nIf this e-mail does not apply to you please ignore it. 
			It appears that you have requested a password reset at our website www.reacoclock.com\n\nTo reset your password, 
			please click the link below. 
			If you cannot click it, please paste it into your web browser's address bar.
			\n\n" . $pwrurl . "\n\nThanks,\nThe Administration";
			
	        mail($userExists["email"], "www.race.com.com - Password Reset", 
			$mailbody);
	        echo "Your password recovery key has been sent to your e-mail address.";
	    }
	    else
	        echo "No user with that e-mail address exists.";
	}
	 
	?> 


Your password recovery key has been sent to your e-mail address.
E-mail Address:
Was This Post Helpful? 0
  • +
  • -

#4 andrewsw  Icon User is online

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3333
  • View blog
  • Posts: 11,298
  • Joined: 12-December 12

Posted 15 March 2013 - 02:59 PM

the docs

Quote

Note:

When sending mail, the mail must contain a From header. This can be set with the additional_headers parameter, or a default can be set in php.ini.

You would receive a warning if this is the case, but you need to turn on all error reporting to see this warning message:

error_reporting(E_ALL);
ini_set('display_errors', '1');

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1