一部のユーザーはパスワードを忘れてしまうため、優れたメンバーシップWebサイトの非常に重要な機能の1つは、パスワードリセットシステムです。このチュートリアルでは、ユーザーのパスワードを回復するための手順の概要を説明します。このチュートリアルでは、PHPとMySQLデータベースを使用してこのようなシステムも実装します。
このようなシステムを実装するプロセス全体は、3つの主要なステップに分けることができます。説明を簡単にするために、ユーザーが入力するために提示するフォームの観点から、これらの手順を分析してみましょう。
- ログインフォーム: このフォームは、ユーザーのユーザー名とパスワードの組み合わせを取得し、システムに登録されている場合はログインします。このフォームには、「パスワードをお忘れですか?」と記載されています。ユーザーがパスワードを忘れてリセットする必要がある場合に備えて、リンクしてください。
- メールフォーム: ユーザーがパスワードを忘れた場合は、「パスワードを忘れましたか?」をクリックできます。ログインページのリンクをクリックしてリセットします。このリンクをクリックすると、メールを入力するように求める別のページに移動します。彼らが提供するメールアドレスがデータベースのusersテーブルにない場合、「そのようなユーザーはシステムに存在しません」というエラーメッセージが表示されます。一方、ユーザーが存在する場合は、一意のトークン(一意のランダムな文字列)を生成し、このトークンをそのメールアドレスと一緒にデータベースのpassword_resetsテーブルに保存します。次に、そのトークンがリンクに含まれているメールを送信します。送信したメールのリンクをクリックすると、別のフォームが表示されたページのウェブサイトに返送されます。
- 新しいパスワードフォーム: ユーザーが再び当社のWebサイトに戻ったら、リンクから取得したトークンを取得して、セッション変数に格納します。次に、当社のWebサイトでアカウントの新しいパスワードを入力するように求めるフォームを提示します。新しいパスワードが送信されると、password_resetsテーブルで、メール内のリンクから取得したばかりのトークンを持つレコードを照会します。トークンがpassword_resetsテーブルで見つかった場合、ユーザーが本人であると確信しており、メール内のリンクをクリックしました。この時点で、password_resets(メールアドレスと一緒にトークンを保存したことを思い出してください)テーブルからユーザーのメールを取得し、そのメールを使用してユーザーテーブルからユーザーを取得してパスワードを更新します。
それが十分に明確であることを願っています。そうでない場合は、そのままにしておくと、実装するにつれて明確になります。
実装
password_recoveryというデータベースを作成し、そのデータベースに、次のフィールドを使用してusersとpassword_resetsの2つのテーブルを作成します。
ユーザー:
+----+-----------+--------------+------------+
| 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 |
+----------------+--------------+------------+
注: このアプリケーションでは、ユーザーがすでにシステムに登録されている必要があります。ただし、このチュートリアルではユーザー登録の部分についてはすでに説明しているため、ここでは取り上げません。最初にそのチュートリアルに従うこともできますが(私はそうすることをお勧めします)、パスワードのリセットに進む前に、データベースのusersテーブルにユーザーがいる必要があることに注意してください。したがって、いずれかの方法で、mysqlデータベースにユーザーを追加します。 PHPMyAdminなどのツールを使用し、md5()を使用してパスワードを暗号化するようにしてください。
次に、password-recoveryというプロジェクトフォルダを作成し、このフォルダがサーバーディレクトリ(htdocsフォルダまたはwwwフォルダ)にあることを確認します。そのフォルダーに、login.php、enter_email.php、new_pass.phpの3つのファイルを作成します。
これらの3つのファイルはそれぞれ、前に概説した3つのステップを表しています。それぞれを開き、次のコードを貼り付けます。
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>
これらの各ファイルには、まだ作成していない3つのファイル、つまりapp_logic.php、messages.php、file、main.cssが含まれていることがわかります。 1つ目は、データベースのクエリ、ユーザーへの電子メールの送信など、アプリケーションのすべてのロジックを処理します。 2つ目は、ユーザーが間違ったメールを入力した場合などのフィードバックメッセージをユーザーに表示し、3つ目はアプリケーションのスタイル設定です。
これらのファイルをpassword-recoveryフォルダーに作成します。 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ステートメントの3つのブロックが表示されます。これらのステートメントは、ユーザーログイン、リセットメールの受信、新しいパスワードの受信という3つのアクションを処理します。 2番目のブロックでは、ユーザーの電子メールアドレスを受信した後、ユーザーはpending.phpページにリダイレクトされます。このページには、パスワードをリセットするために使用できるメールアドレスにメールが送信されたことをユーザーに通知するメッセージが表示されます。
プロジェクトのルートフォルダにpending.phpを作成し、その中に次のコードを追加します:
保留中.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で開き、試してみます。
注: PHPのmail()関数を使用して、ユーザーに電子メールを送信しました。この関数はローカルホストからメールを送信できません。これは、インターネット上でホストされているサーバーを使用してのみ行うことができます。ただし、ローカルシステムでデモを行いたい場合は、テストメールアプリケーションを使用してメールの送信をシミュレートできます。
結論
このチュートリアルを最後まで実行していただき、ありがとうございます。説明が十分に明確であり、Web開発に役立つ何かを学んだことを願っています。問題や懸念がある場合は、下のコメントにそれらをドロップすることを忘れないでください。私があなたに連絡します。
良い一日を!