Jedną z bardzo ważnych funkcji każdej dobrej strony internetowej z członkostwem jest system resetowania hasła, ponieważ niektórzy użytkownicy są zobowiązani do zapomnienia hasła. W tym samouczku opisuję kroki związane z odzyskiwaniem hasła użytkownika; w tym samouczku będziemy również wdrażać taki system przy użyciu PHP i bazy danych MySQL.
Cały proces wdrażania takiego systemu można podzielić na 3 główne kroki. Aby ułatwić wyjaśnienie, przeanalizujmy te kroki pod kątem formularzy, które przedstawimy użytkownikowi do wypełnienia:
- Formularz logowania: Ten formularz pobiera kombinację nazwy użytkownika i hasła użytkownika i loguje je, jeśli są zarejestrowane w systemie. W tym formularzu podajemy "Zapomniałeś hasła?" link na wypadek, gdyby użytkownik zapomniał hasła i musiał je zresetować.
- Formularz e-mail: Jeśli użytkownik zapomniał hasła, może kliknąć opcję „Zapomniałeś hasła?” link na stronie logowania, aby go zresetować. Kliknięcie tego linku przeniesie ich na inną stronę z prośbą o wpisanie adresu e-mail. Gdy podany przez nich adres e-mail nie znajduje się w naszej tabeli użytkowników w bazie danych, zostanie wyświetlony komunikat o błędzie „Nie ma takiego użytkownika w naszym systemie”. Jeśli z drugiej strony użytkownik istnieje, wygenerujemy unikalny token (unikalny losowy ciąg) i przechowamy ten token wraz z tym adresem e-mail w tabeli password_resets w bazie danych. Następnie wyślemy im e-mail, który zawiera ten token w linku. Gdy klikną link w e-mailu, który im wysłaliśmy, zostaną odesłani z powrotem do naszej witryny na stronie, która przedstawia im inny formularz.
- Formularz nowego hasła: Gdy użytkownik ponownie pojawi się na naszej stronie, pobierzemy token pochodzący z linku i zapiszemy go w zmiennej sesji. Następnie przedstawimy im formularz z prośbą o podanie nowego hasła do konta na naszej stronie. Po przesłaniu nowego hasła wyślemy zapytanie do tabeli password_resets o rekord, który zawiera token, który właśnie pochodzi z linku w wiadomości e-mail. Jeśli token zostanie znaleziony w tabeli password_reset, jesteśmy pewni, że użytkownik jest tym, kim jest i kliknął link w swojej poczcie. W tym momencie pobieramy e-mail użytkownika z tabeli password_reset (pamiętaj, że zapisaliśmy token wraz z jego adresem e-mail) i używamy tego e-maila, aby pobrać użytkownika z tabeli użytkowników i zaktualizować jego hasło.
Mam nadzieję, że to wystarczająco jasne. Jeśli nie, po prostu trzymaj się, a stanie się to jaśniejsze w miarę wdrażania.
Wdrożenie
Utwórz bazę danych o nazwie password_recovery i w tej bazie danych utwórz dwie tabele, a mianowicie users i password_reset z następującymi polami:
użytkownicy:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| username | VARCHAR(255) | |
| email | VARCHAR(255) | UNIQUE |
| password | VARCHAR(255) | |
+----------------+--------------+------------+
password_reset:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| email | VARCHAR(255) | |
| token | VARCHAR(255) | UNIQUE |
+----------------+--------------+------------+
Uwaga: Ta aplikacja wymaga, aby użytkownik był już zarejestrowany w systemie. Ale nie będziemy omawiać części rejestracji użytkownika w tym samouczku, ponieważ została ona już omówiona na tej stronie. Możesz najpierw skorzystać z tego samouczka (polecam) lub nie, ale pamiętaj, że musimy mieć użytkownika w naszej tabeli użytkowników w bazie danych, zanim będziemy mogli przystąpić do resetowania jego hasła. Tak czy inaczej, dodaj użytkownika do swojej bazy danych mysql. Możesz użyć narzędzia takiego jak PHPMyAdmin i upewnić się, że szyfrujesz hasło za pomocą md5().
Teraz utwórz folder projektu o nazwie odzyskiwanie hasła i upewnij się, że ten folder znajduje się w katalogu serwera (folder htdocs lub folder www). W tym folderze utwórz trzy pliki a mianowicie:login.php, enter_email.php, new_pass.php:
Każdy z tych trzech plików reprezentuje trzy kroki, które opisaliśmy wcześniej. Otwórz każdy z nich i wklej do nich następujące kody:
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>
W każdym z tych plików widać, że uwzględniamy trzy pliki, których jeszcze nie utworzyliśmy, a mianowicie app_logic.php , messages.php,file i main.css. Pierwsza obsługuje całą logikę naszej aplikacji, taką jak odpytywanie bazy danych, wysyłanie wiadomości e-mail do użytkownika i nie tylko; drugi wyświetla użytkownikowi komunikaty zwrotne, takie jak wpisanie nieprawidłowego adresu e-mail, trzeci to styl aplikacji.
Utwórz te pliki w folderze odzyskiwania hasła. W pliku main.css dodaj ten kod stylizacji:
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');
}
}
}
?>
Tutaj widzisz trzy bloki instrukcji if. Oświadczenia te obsługują trzy czynności, a mianowicie logowanie użytkownika, odbieranie wiadomości e-mail o zresetowaniu i odbieranie nowego hasła. W drugim bloku, po otrzymaniu adresu e-mail użytkownika, zostaje on przekierowany na stronę pending.php. Ta strona wyświetla po prostu komunikat informujący użytkownika, że na jego adres e-mail wysłano wiadomość e-mail, której może użyć do zresetowania hasła.
Utwórz pending.php w folderze głównym naszego projektu i dodaj do niego ten kod:
oczekujący.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 to plik, który przechowuje fragment kodu do wyświetlania komunikatów o błędach w formularzu. Otwórz go i wklej w nim ten kod:
wiadomości.php:
<?php if (count($errors) > 0) : ?>
<div class="msg">
<?php foreach ($errors as $error) : ?>
<span><?php echo $error ?></span>
<?php endforeach ?>
</div>
<?php endif ?>
Teraz otwórz ten projekt w przeglądarce pod adresem http://localhost/password-recovery/login.php i baw się nim.
Uwaga: Użyliśmy funkcji mail() PHP do wysłania wiadomości e-mail do użytkownika. Ta funkcja nie może wysyłać wiadomości e-mail z hosta lokalnego. Może to zrobić tylko za pomocą serwera hostowanego w Internecie. Możemy jednak użyć testowej aplikacji pocztowej do symulacji wysyłania e-maili, jeśli chcesz mieć wersję demonstracyjną w swoim lokalnym systemie.
Wniosek
Dziękujemy za wykonanie tego samouczka do końca. Mam nadzieję, że wyjaśnienie było wystarczająco jasne i nauczyłeś się czegoś, co może ci pomóc w tworzeniu stron internetowych. Jeśli masz jakieś problemy lub wątpliwości, nie zapomnij wrzucić ich w komentarzach poniżej, a ja się z Tobą skontaktuję.
Miłego dnia!