Sunday 1 January 2017

Forgot Password Recovery in Login System with PHP and MySQL

Forgot password recovery feature is mandatory for login system. It helps the user to update account password which they have forgotten. Using forgot password link user can easily reset their account password. In this tutorial, we’ll show you the forgot password recovery process and create a script to implement forgot password email functionality in PHP Login System. Our previous PHP Login System tutorial had provided a guide to implementing user registration and login system in PHP. Now we’ll extend that PHP login script with forgot password functionality with PHP and MySQL. Also, we’ll show you how can send reset password link via email to the user. Before you begin with this forgot password recovery tutorial, we suggest go through the previous PHP login system tutorial first. Here the files list that is used in forgot password recovery process. user.php – handle database related works userAccount.php – handle forgot password, reset password, and email sending. index.php – display login form with forgot password link. forgotPassword.php – display forgot password form. resetPassword.php – display reset password form. style.css – styling login, forgot, and reset form. Database Table Creation To store the user details you already have a users table in the MySQL database. Now add a column named forgot_pass_identity to user table. ALTER TABLE `users` ADD `forgot_pass_identity` VARCHAR(32) NOT NULL AFTER `phone`; Entire users table SQL will like the following. CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `first_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `last_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `phone` varchar(15) COLLATE utf8_unicode_ci NOT NULL, `forgot_pass_identity` varchar(32) COLLATE utf8_unicode_ci NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; User Class (user.php) User Class handles all the database related works, like get, insert, update user data. This class has extended with one method (update()) for update forgot password identity code in the users table. db)){ // Connect to the database $conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName); if($conn->connect_error){ die("Failed to connect with MySQL: " . $conn->connect_error); }else{ $this->db = $conn; } } } /* * Returns rows from the database based on the conditions * @param string name of the table * @param array select, where, order_by, limit and return_type conditions */ public function getRows($conditions = array()){ $sql = 'SELECT '; $sql .= array_key_exists("select",$conditions)?$conditions['select']:'*'; $sql .= ' FROM '.$this->userTbl; if(array_key_exists("where",$conditions)){ $sql .= ' WHERE '; $i = 0; foreach($conditions['where'] as $key => $value){ $pre = ($i > 0)?' AND ':''; $sql .= $pre.$key." = '".$value."'"; $i++; } } if(array_key_exists("order_by",$conditions)){ $sql .= ' ORDER BY '.$conditions['order_by']; } if(array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){ $sql .= ' LIMIT '.$conditions['start'].','.$conditions['limit']; }elseif(!array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){ $sql .= ' LIMIT '.$conditions['limit']; } $result = $this->db->query($sql); if(array_key_exists("return_type",$conditions) && $conditions['return_type'] != 'all'){ switch($conditions['return_type']){ case 'count': $data = $result->num_rows; break; case 'single': $data = $result->fetch_assoc(); break; default: $data = ''; } }else{ if($result->num_rows > 0){ while($row = $result->fetch_assoc()){ $data[] = $row; } } } return !empty($data)?$data:false; } /* * Insert data into the database * @param string name of the table * @param array the data for inserting into the table */ public function insert($data){ if(!empty($data) && is_array($data)){ $columns = ''; $values = ''; $i = 0; if(!array_key_exists('created',$data)){ $data['created'] = date("Y-m-d H:i:s"); } if(!array_key_exists('modified',$data)){ $data['modified'] = date("Y-m-d H:i:s"); } foreach($data as $key=>$val){ $pre = ($i > 0)?', ':''; $columns .= $pre.$key; $values .= $pre."'".$val."'"; $i++; } $query = "INSERT INTO ".$this->userTbl." (".$columns.") VALUES (".$values.")"; $insert = $this->db->query($query); return $insert?$this->db->insert_id:false; }else{ return false; } } /* * Update data into the database * @param string name of the table * @param array the data for inserting into the table */ public function update($data, $conditions){ if(!empty($data) && is_array($data) && !empty($conditions)){ //prepare columns and values sql $cols_vals = ''; $i = 0; if(!array_key_exists('modified',$data)){ $data['modified'] = date("Y-m-d H:i:s"); } foreach($data as $key=>$val){ $pre = ($i > 0)?', ':''; $cols_vals .= $pre.$key." = '".$val."'"; $i++; } //prepare where conditions $whereSql = ''; $ci = 0; foreach($conditions as $key => $value){ $pre = ($ci > 0)?' AND ':''; $whereSql .= $pre.$key." = '".$value."'"; $ci++; } //prepare sql query $query = "UPDATE ".$this->userTbl." SET ".$cols_vals." WHERE ".$whereSql; //update data $update = $this->db->query($query); return $update?true:false; }else{ return false; } } } userAccount.php This file controls the registration, login, logout, forgot password, and reset password request. This script has extended with two requests forgotSubmit and resetSubmit. Also, the email sending functionality is added in forgotSubmit request to send the email with reset password link to the user. $_POST['email']); $prevCon['return_type'] = 'count'; $prevUser = $user->getRows($prevCon); if($prevUser > 0){ //generat unique string $uniqidStr = md5(uniqid(mt_rand()));; //update data with forgot pass code $conditions = array( 'email' => $_POST['email'] ); $data = array( 'forgot_pass_identity' => $uniqidStr ); $update = $user->update($data, $conditions); if($update){ $resetPassLink = 'http://codexworld.com/resetPassword.php?fp_code='.$uniqidStr; //get user details $con['where'] = array('email'=>$_POST['email']); $con['return_type'] = 'single'; $userDetails = $user->getRows($con); //send reset password email $to = $userDetails['email']; $subject = "Password Update Request"; $mailContent = 'Dear '.$userDetails['first_name'].',
Recently a request was submitted to reset a password for your account. If this was a mistake, just ignore this email and nothing will happen.
To reset your password, visit the following link: '.$resetPassLink.'

Regards,
CodexWorld'; //set content-type header for sending HTML email $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; //additional headers $headers .= 'From: CodexWorld' . "\r\n"; //send email mail($to,$subject,$mailContent,$headers); $sessData['status']['type'] = 'success'; $sessData['status']['msg'] = 'Please check your e-mail, we have sent a password reset link to your registered email.'; }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'Some problem occurred, please try again.'; } }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'Given email is not associated with any account.'; } }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'Enter email to create a new password for your account.'; } //store reset password status into the session $_SESSION['sessData'] = $sessData; //redirect to the forgot pasword page header("Location:forgotPassword.php"); }elseif(isset($_POST['resetSubmit'])){ $fp_code = ''; if(!empty($_POST['password']) && !empty($_POST['confirm_password']) && !empty($_POST['fp_code'])){ $fp_code = $_POST['fp_code']; //password and confirm password comparison if($_POST['password'] !== $_POST['confirm_password']){ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'Confirm password must match with the password.'; }else{ //check whether identity code exists in the database $prevCon['where'] = array('forgot_pass_identity' => $fp_code); $prevCon['return_type'] = 'single'; $prevUser = $user->getRows($prevCon); if(!empty($prevUser)){ //update data with new password $conditions = array( 'forgot_pass_identity' => $fp_code ); $data = array( 'password' => md5($_POST['password']) ); $update = $user->update($data, $conditions); if($update){ $sessData['status']['type'] = 'success'; $sessData['status']['msg'] = 'Your account password has been reset successfully. Please login with your new password.'; }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'Some problem occurred, please try again.'; } }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'You does not authorized to reset new password of this account.'; } } }else{ $sessData['status']['type'] = 'error'; $sessData['status']['msg'] = 'All fields are mandatory, please fill all the fields.'; } //store reset password status into the session $_SESSION['sessData'] = $sessData; $redirectURL = ($sessData['status']['type'] == 'success')?'index.php':'resetPassword.php?fp_code='.$fp_code; //redirect to the login/reset pasword page header("Location:".$redirectURL); } Note that: Don’t forget to change the email content, from address, and website base URL in $resetPassLink as per your project requirement. Login Form with Forgot Password Link (index.php) A forgot password link is added in the existing login form for navigating user to forgot password form.
Forgot Password Form (forgotPassword.php) A form displays to collect the account email for identifying user account. The form is submitted to the userAccount.php file with a forgotSubmit request.

Enter the Email of Your Account to Reset New Password

'.$statusMsg.'':''; ?>

Reset Password Form (resetPassword.php) This script is loaded when the user clicks on the reset password link in the mail. A form will appear to update account password and the form is submitted to the userAccount.php file with a resetSubmit request.

Reset Your Account Password

'.$statusMsg.'':''; ?>

CSS Code (style.css) No new CSS code are added to implement forgot password functionality. The same CSS file is included from our login system. .container { width: 40%; margin: 0 auto; background-color: #f7f7f7; color: #757575; font-family: 'Raleway', sans-serif; text-align: left; padding: 30px; } h2 { font-size: 30px; font-weight: 600; margin-bottom: 10px; } .container p { font-size: 18px; font-weight: 500; margin-bottom: 20px; } .regisFrm input[type="text"], .regisFrm input[type="email"], .regisFrm input[type="password"] { width: 94.5%; padding: 10px; margin: 10px 0; outline: none; color: #000; font-weight: 500; font-family: 'Roboto', sans-serif; } .send-button { text-align: center; margin-top: 20px; } .send-button input[type="submit"] { padding: 10px 0; width: 60%; font-family: 'Roboto', sans-serif; font-size: 18px; font-weight: 500; border: none; outline: none; color: #FFF; background-color: #2196F3; cursor: pointer; } .send-button input[type="submit"]:hover { background-color: #055d54; } a.logout{float: right;} p.success{color:#34A853;} p.error{color:#EA4335;} Conclusion Hope this tutorial will help you to implement forgot password recovery system with reset email sending feature. Here we’ve tried to extend our previous login system script with simple forgot password functionality.

No comments:

Post a Comment