Една много важна характеристика на всеки добър уебсайт за членство е система за нулиране на парола, защото някои потребители са длъжни да забравят паролата си. В този урок очертавам стъпките, свързани с възстановяването на потребителска парола; ние също така ще внедрим такава система, използвайки PHP и MySQL база данни в този урок.
Целият процес на внедряване на такава система може да бъде разделен на 3 основни стъпки. За да улесним обяснението, нека анализираме тези стъпки по отношение на формулярите, които ще представим за попълване на потребителя:
- Формуляр за вход: Този формуляр взема комбинацията от потребителско име и парола на потребител и ги влиза, ако е регистриран в системата. В този формуляр предоставяме "Забравена парола?" връзка в случай, че потребителят е забравил паролата си и трябва да я нулира.
- Формуляр за имейл: Ако потребителят е забравил паролата си, той може да щракне върху "Забравена парола?" връзка на страницата за вход, за да го нулирате. Кликването върху тази връзка ще ги отведе до друга страница, която ги подканва да въведат имейла. Когато имейл адресът, който предоставят, не е в нашата таблица с потребители в базата данни, ще покажем и съобщение за грешка, което гласи „Няма такъв потребител в нашата система“. Ако, от друга страна, потребителят съществува, ние ще генерираме уникален токен (уникален произволен низ) и ще съхраняваме този токен заедно с този имейл адрес в таблицата password_resets в базата данни. След това ще им изпратим имейл, който съдържа този токен във връзка. Когато щракнат върху връзката в имейла, който им изпратихме, те ще бъдат изпратени обратно на нашия уебсайт на страница, която им представя друг формуляр.
- Формуляр за нова парола: След като потребителят се върне отново на нашия уебсайт, ние ще вземем токена, който идва от връзката, и ще го съхраним в променлива на сесията. След това ще им представим формуляр, който ги моли да въведат нова парола за акаунта си на нашия уебсайт. Когато новата парола бъде изпратена, ние ще потърсим таблицата password_resets за записа, който има този маркер, който току-що дойде от връзката в пощата. Ако токенът бъде намерен в таблицата password_resets, тогава ние сме уверени, че потребителят е този, който е и е щракнал върху връзката в пощата си. В този момент сега грабваме имейла на потребителя от таблицата password_resets (не забравяйте, че сме запазили токена до неговия имейл адрес) и използваме този имейл, извличаме потребителя от таблицата с потребители и актуализираме паролата му.
Надявам се това да е достатъчно ясно. Ако не, просто останете и ще стане по-ясно, докато прилагаме.
Внедряване
Създайте база данни, наречена password_recovery и в тази база данни създайте две таблици, а именно потребители и password_resets със следните полета:
потребители:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| username | VARCHAR(255) | |
| email | VARCHAR(255) | UNIQUE |
| password | VARCHAR(255) | |
+----------------+--------------+------------+
нулиране на парола:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| email | VARCHAR(255) | |
| token | VARCHAR(255) | UNIQUE |
+----------------+--------------+------------+
Забележка: Това приложение изисква потребителят вече да е регистриран в системата. Но ние няма да разглеждаме частта за регистрация на потребител в този урок, защото тя вече е разгледана на този сайт. Можете първо да следвате този урок (препоръчвам ви да го направите) или не, но имайте предвид, че трябва да имаме потребител в нашата таблица с потребители в базата данни, преди да можем да продължим да нулираме паролата му. Така че по един или друг начин добавете потребител към вашата mysql база данни. Можете да използвате инструмент като PHPMyAdmin и да се уверите, че шифровате паролата с помощта на md5().
Сега създайте папка на проекта, наречена Password-recovery и се уверете, че тази папка е в директорията на вашия сървър (папка htdocs или папка www). В тази папка създайте три файла, а именно:login.php, enter_email.php, new_pass.php:
Всеки от тези три файла представлява трите стъпки, които очертахме по-рано. Отворете всеки от тях и поставете в тях следните кодове:
login.php:
<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Password Reset PHP</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<form class="login-form" action="login.php" method="post">
<h2 class="form-title">Login</h2>
<!-- form validation messages -->
<?php include('messages.php'); ?>
<div class="form-group">
<label>Username or Email</label>
<input type="text" value="<?php echo $user_id; ?>" name="user_id">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password">
</div>
<div class="form-group">
<button type="submit" name="login_user" class="login-btn">Login</button>
</div>
<p><a href="enter_email.php">Forgot your password?</a></p>
</form>
</body>
</html>
enter_email.php:
<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Password Reset PHP</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<form class="login-form" action="enter_email.php" method="post">
<h2 class="form-title">Reset password</h2>
<!-- form validation messages -->
<?php include('messages.php'); ?>
<div class="form-group">
<label>Your email address</label>
<input type="email" name="email">
</div>
<div class="form-group">
<button type="submit" name="reset-password" class="login-btn">Submit</button>
</div>
</form>
</body>
</html>
new_pass.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Password Reset PHP</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<form class="login-form" action="new_password.php" method="post">
<h2 class="form-title">New password</h2>
<!-- form validation messages -->
<?php include('messages.php'); ?>
<div class="form-group">
<label>New password</label>
<input type="password" name="new_pass">
</div>
<div class="form-group">
<label>Confirm new password</label>
<input type="password" name="new_pass_c">
</div>
<div class="form-group">
<button type="submit" name="new_password" class="login-btn">Submit</button>
</div>
</form>
</body>
</html>
Във всеки от тези файлове виждате, че включваме три файла, които все още не сме създали, а именно app_logic.php , messages.php,file и main.css. Първият обработва цялата логика на нашето приложение, като например запитване в базата данни, изпращане на имейл до потребителя и други; вторият показва съобщения за обратна връзка до потребителя, като например когато въведе грешен имейл, третият е стилът на приложението.
Създайте тези файлове в папката за възстановяване на парола. Във файла main.css добавете този код за стил:
main.css:
body {
background: #3b5998;
font-size: 1.1em;
font-family: sans-serif;
}
a {
text-decoration: none;
}
form {
width: 25%;
margin: 70px auto;
background: white;
padding: 10px;
border-radius: 3px;
}
h2.form-title {
text-align: center;
}
input {
display: block;
box-sizing: border-box;
width: 100%;
padding: 8px;
}
form .form-group {
margin: 10px auto;
}
form button {
width: 100%;
border: none;
color: white;
background: #3b5998;
padding: 15px;
border-radius: 5px;
}
.msg {
margin: 5px auto;
border-radius: 5px;
border: 1px solid red;
background: pink;
text-align: left;
color: brown;
padding: 10px;
}
app_logic.php:
<?php
session_start();
$errors = [];
$user_id = "";
// connect to database
$db = mysqli_connect('localhost', 'root', '', 'password-reset-php');
// LOG USER IN
if (isset($_POST['login_user'])) {
// Get username and password from login form
$user_id = mysqli_real_escape_string($db, $_POST['user_id']);
$password = mysqli_real_escape_string($db, $_POST['password']);
// validate form
if (empty($user_id)) array_push($errors, "Username or Email is required");
if (empty($password)) array_push($errors, "Password is required");
// if no error in form, log user in
if (count($errors) == 0) {
$password = md5($password);
$sql = "SELECT * FROM users WHERE username='$user_id' OR email='$user_id' AND password='$password'";
$results = mysqli_query($db, $sql);
if (mysqli_num_rows($results) == 1) {
$_SESSION['username'] = $user_id;
$_SESSION['success'] = "You are now logged in";
header('location: index.php');
}else {
array_push($errors, "Wrong credentials");
}
}
}
/*
Accept email of user whose password is to be reset
Send email to user to reset their password
*/
if (isset($_POST['reset-password'])) {
$email = mysqli_real_escape_string($db, $_POST['email']);
// ensure that the user exists on our system
$query = "SELECT email FROM users WHERE email='$email'";
$results = mysqli_query($db, $query);
if (empty($email)) {
array_push($errors, "Your email is required");
}else if(mysqli_num_rows($results) <= 0) {
array_push($errors, "Sorry, no user exists on our system with that email");
}
// generate a unique random token of length 100
$token = bin2hex(random_bytes(50));
if (count($errors) == 0) {
// store token in the password-reset database table against the user's email
$sql = "INSERT INTO password_reset(email, token) VALUES ('$email', '$token')";
$results = mysqli_query($db, $sql);
// Send email to user with the token in a link they can click on
$to = $email;
$subject = "Reset your password on examplesite.com";
$msg = "Hi there, click on this <a href=\"new_password.php?token=" . $token . "\">link</a> to reset your password on our site";
$msg = wordwrap($msg,70);
$headers = "From: [email protected]";
mail($to, $subject, $msg, $headers);
header('location: pending.php?email=' . $email);
}
}
// ENTER A NEW PASSWORD
if (isset($_POST['new_password'])) {
$new_pass = mysqli_real_escape_string($db, $_POST['new_pass']);
$new_pass_c = mysqli_real_escape_string($db, $_POST['new_pass_c']);
// Grab to token that came from the email link
$token = $_SESSION['token'];
if (empty($new_pass) || empty($new_pass_c)) array_push($errors, "Password is required");
if ($new_pass !== $new_pass_c) array_push($errors, "Password do not match");
if (count($errors) == 0) {
// select email address of user from the password_reset table
$sql = "SELECT email FROM password_reset WHERE token='$token' LIMIT 1";
$results = mysqli_query($db, $sql);
$email = mysqli_fetch_assoc($results)['email'];
if ($email) {
$new_pass = md5($new_pass);
$sql = "UPDATE users SET password='$new_pass' WHERE email='$email'";
$results = mysqli_query($db, $sql);
header('location: index.php');
}
}
}
?>
Тук виждате три блока от оператори if. Тези изявления обработват три действия, а именно влизане на потребител, получаване на имейл за нулиране и получаване на нова парола. Във втория блок, след като получи имейл адреса на потребителя, потребителят се пренасочва към страница pending.php. Тази страница просто показва съобщение, което казва на потребителя, че имейл адресът му е изпратен на имейл адреса, който те могат да използват, за да нулират паролата си.
Създайте pending.php в основната папка на нашия проект и добавете този код вътре:
pending.php:
<?php include('app_logic.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Password Reset PHP</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<form class="login-form" action="login.php" method="post" style="text-align: center;">
<p>
We sent an email to <b><?php echo $_GET['email'] ?></b> to help you recover your account.
</p>
<p>Please login into your email account and click on the link we sent to reset your password</p>
</form>
</body>
</html>
messages.php е файл, който съдържа кодовия фрагмент за показване на съобщения за грешки във формуляра. Отворете го и поставете този код вътре:
messages.php:
<?php if (count($errors) > 0) : ?>
<div class="msg">
<?php foreach ($errors as $error) : ?>
<span><?php echo $error ?></span>
<?php endforeach ?>
</div>
<?php endif ?>
Сега отворете този проект в браузъра си на http://localhost/password-recovery/login.php и играйте с него.
Забележка: Използвахме функцията mail() на PHP, за да изпратим имейл до потребителя. Тази функция не може да изпраща имейли от localhost. Може да направи това само с помощта на сървър, който се хоства в интернет. Въпреки това можем да използваме тестово приложение за електронна поща, за да симулираме изпращането на имейли, ако искате да имате демонстрация във вашата локална система.
Заключение
Благодарим ви, че следвате този урок до края. Надявам се, че обяснението е било достатъчно ясно и сте научили нещо, което може да ви бъде от полза в уеб разработката. Ако имате някакви проблеми или притеснения, не забравяйте да ги оставите в коментарите по-долу и аз ще се свържа с вас.
Приятен ден!