Jedním z velmi důležitých rysů každé dobré webové stránky pro členství je systém resetování hesla, protože někteří uživatelé musí své heslo zapomenout. V tomto tutoriálu nastíním kroky spojené s obnovením hesla uživatele; v tomto tutoriálu budeme také implementovat takový systém pomocí PHP a databáze MySQL.
Celý proces implementace takového systému lze rozdělit do 3 hlavních kroků. Abychom usnadnili vysvětlení, pojďme analyzovat tyto kroky z hlediska formulářů, které uživateli předložíme k vyplnění:
- Přihlašovací formulář: Tento formulář přebírá kombinaci uživatelského jména a hesla uživatele a přihlašuje jej, pokud je registrován v systému. V tomto formuláři poskytujeme "Zapomněli jste heslo?" odkaz v případě, že uživatel zapomněl své heslo a potřebuje ho obnovit.
- E-mailový formulář: Pokud uživatel zapomněl své heslo, může kliknout na odkaz "Zapomněli jste heslo?" odkaz na přihlašovací stránce, abyste jej resetovali. Kliknutím na tento odkaz přejdou na další stránku, která je vyzve k zadání e-mailu. Když e-mailová adresa, kterou poskytují, není v naší tabulce uživatelů v databázi, zobrazí se chybová zpráva, která říká „V našem systému neexistuje žádný takový uživatel“. Pokud na druhou stranu uživatel existuje, vygenerujeme jedinečný token (jedinečný náhodný řetězec) a uložíme tento token společně s touto e-mailovou adresou do tabulky password_reset v databázi. Poté jim zašleme e-mail, který má tento token v odkazu. Když kliknou na odkaz v e-mailu, který jsme jim poslali, budou přesměrováni zpět na náš web na stránku, která jim nabídne jiný formulář.
- Formulář nového hesla: Jakmile se uživatel znovu vrátí na náš web, vezmeme token, který pochází z odkazu, a uložíme jej do proměnné relace. Poté jim předložíme formulář, který je požádá o zadání nového hesla ke svému účtu na našem webu. Po odeslání nového hesla se dotážeme v tabulce password_reset na záznam, který má token, který právě přišel z odkazu v e-mailu. Pokud je token nalezen v tabulce password_resets, pak jsme si jisti, že jejich uživatel je tím, kým je, a klikl na odkaz ve své poště. V tomto okamžiku nyní získáme e-mail uživatele z tabulky password_reset (nezapomeňte, že jsme token uložili vedle jeho e-mailové adresy) a pomocí tohoto e-mailu načteme uživatele z tabulky uživatelů a aktualizujeme jeho heslo.
Doufám, že je to dostatečně jasné. Pokud ne, držte se a při implementaci to bude jasnější.
Implementace
Vytvořte databázi s názvem password_recovery a v této databázi vytvořte dvě tabulky, jmenovitě users a password_resets s následujícími poli:
uživatelé:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| username | VARCHAR(255) | |
| email | VARCHAR(255) | UNIQUE |
| password | VARCHAR(255) | |
+----------------+--------------+------------+
password_resets:
+----+-----------+--------------+------------+
| field | type | specs |
+----+-----------+--------------+------------+
| id | INT(11) | |
| email | VARCHAR(255) | |
| token | VARCHAR(255) | UNIQUE |
+----------------+--------------+------------+
Poznámka: Tato aplikace vyžaduje, aby byl uživatel již zaregistrován v systému. V tomto tutoriálu se však nebudeme zabývat registrací uživatele, protože na tomto webu již byla popsána. Můžete nejprve postupovat podle tohoto návodu (doporučuji vám to), nebo ne, ale mějte na paměti, že potřebujeme mít uživatele v naší tabulce uživatelů v databázi, než budeme moci přistoupit k resetování jeho hesla. Takže tak či onak přidejte uživatele do své databáze mysql. Můžete použít nástroj jako PHPMyAdmin a ujistit se, že heslo zašifrujete pomocí md5().
Nyní vytvořte složku projektu s názvem Password-recovery a ujistěte se, že je tato složka v adresáři vašeho serveru (složka htdocs nebo složka www). V této složce vytvořte tři soubory, jmenovitě:login.php, enter_email.php, new_pass.php:
Každý z těchto tří souborů představuje tři kroky, které jsme nastínili dříve. Otevřete každou z nich a vložte do nich následující kódy:
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>
V každém z těchto souborů vidíte, že zahrnujeme tři soubory, které jsme ještě nevytvořili, a to app_logic.php , messages.php,file a main.css. První řeší veškerou logiku naší aplikace, jako je dotazování na databázi, odesílání e-mailů uživateli a další; druhý zobrazuje zpětnou vazbu pro uživatele, například když zadá špatný e-mail, třetí je styl aplikace.
Vytvořte tyto soubory ve složce pro obnovení hesla. Do souboru main.css přidejte tento stylingový kód:
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');
}
}
}
?>
Zde vidíte tři bloky příkazů if. Tato prohlášení zpracovávají tři akce, jmenovitě přihlášení uživatele, obdržení resetovacího e-mailu a obdržení nového hesla. Ve druhém bloku, po obdržení e-mailové adresy uživatele, je uživatel přesměrován na stránku čekající.php. Tato stránka jednoduše zobrazí zprávu sdělující uživateli, že na jeho e-mailovou adresu byl odeslán e-mail, který může použít k obnovení hesla.
Vytvořte pending.php v kořenové složce našeho projektu a přidejte do ní tento kód:
čekající.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 je soubor, který obsahuje fragment kódu pro zobrazení chybových zpráv ve formuláři. Otevřete jej a vložte do něj tento kód:
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 ?>
Nyní otevřete tento projekt ve svém prohlížeči na adrese http://localhost/password-recovery/login.php a hrajte si s ním.
Poznámka: K odeslání e-mailu uživateli jsme použili funkci mail() PHP. Tato funkce nemůže odesílat e-maily z localhost. Může tak učinit pouze pomocí serveru, který je hostován na internetu. Můžeme však použít testovací poštovní aplikaci k simulaci odesílání e-mailů, pokud chcete mít demo na vašem místním systému.
Závěr
Děkujeme, že jste tento návod dodrželi až do konce. Doufám, že vysvětlení bylo dostatečně jasné a dozvěděli jste se něco, co vám může pomoci při vývoji webu. Pokud máte nějaké problémy nebo obavy, nezapomeňte je napsat do komentářů níže a já se vám ozvu.
Přeji hezký den!