sql >> データベース >  >> RDS >> Mysql

PHPのパスワードリセットシステム

    一部のユーザーはパスワードを忘れてしまうため、優れたメンバーシップWebサイトの非常に重要な機能の1つは、パスワードリセットシステムです。このチュートリアルでは、ユーザーのパスワードを回復するための手順の概要を説明します。このチュートリアルでは、PHPとMySQLデータベースを使用してこのようなシステムも実装します。

    このようなシステムを実装するプロセス全体は、3つの主要なステップに分けることができます。説明を簡単にするために、ユーザーが入力するために提示するフォームの観点から、これらの手順を分析してみましょう。

    1. ログインフォーム: このフォームは、ユーザーのユーザー名とパスワードの組み合わせを取得し、システムに登録されている場合はログインします。このフォームには、「パスワードをお忘れですか?」と記載されています。ユーザーがパスワードを忘れてリセットする必要がある場合に備えて、リンクしてください。
    2. メールフォーム: ユーザーがパスワードを忘れた場合は、「パスワードを忘れましたか?」をクリックできます。ログインページのリンクをクリックしてリセットします。このリンクをクリックすると、メールを入力するように求める別のページに移動します。彼らが提供するメールアドレスがデータベースのusersテーブルにない場合、「そのようなユーザーはシステムに存在しません」というエラーメッセージが表示されます。一方、ユーザーが存在する場合は、一意のトークン(一意のランダムな文字列)を生成し、このトークンをそのメールアドレスと一緒にデータベースのpassword_resetsテーブルに保存します。次に、そのトークンがリンクに含まれているメールを送信します。送信したメールのリンクをクリックすると、別のフォームが表示されたページのウェブサイトに返送されます。
    3. 新しいパスワードフォーム: ユーザーが再び当社の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開発に役立つ何かを学んだことを願っています。問題や懸念がある場合は、下のコメントにそれらをドロップすることを忘れないでください。私があなたに連絡します。

    良い一日を!


    1. Mod()がPostgreSQLでどのように機能するか

    2. PostgreSQL、レシピで材料を計算するための複雑なクエリ

    3. MariaDBクラスターにMaxCtrlを使用したMaxScale基本管理

    4. 各グループの上位1行を取得