Сброс пароля на PHP


Одна из целей разработки учебных проектов – это возможность разобраться с тем, как внутри работают некоторые процессы. Это относится и к функции сброса пароля пользователя (если забыл), которая реализована во всех крупных кмс, крм и фреймворках по умолчанию. Но полезно реализовать и самостоятельный вариант – хотя бы в учебных целях – давайте этим и займёмся.

Ход решения

Сначала посмотрим, что уже внутри есть у нашего веб-приложения (то бишь сайта). А видим мы обычную таблицу пользователей с оригинальным названием users и четырьмя полями – ид, логин, пароль и right (понятно, что это что-то типа прав доступа). Что ж, тогда реализуем самый простой вариант (не забываем, что у нас учебный проект).

Этапы:
  1. Добавляем в таблицу users два поля: email и reset_token.
  2. На форму регистрации добавляем инпут для электронной почты.
  3. В скрипт (функцию регистрации) вставляем добавление поля email.
  4. Создаем форму для ввода email для сброса.
  5. Создаем функцию, проверяющую, есть ли введенный mail в системе, создающую токен и отправляющую ссылку для сброса на почту.
  6. Создаем форму для ввода нового пароля.
  7. Создаем функцию, которая вызывается при переходе по этой ссылке – которая собственно и сбрасывает пароль на введенный.
Теперь каждый из этапов разберем подробнее.

1 Миграция

Добавление полей в таблицу – это обычная миграция, sql-запрос. Тут будет что-то типа такого

ALTER TABLE `users` ADD `email` VARCHAR(255) NOT NULL AFTER `reset_token`, ADD `reset_token` VARCHAR(255) NOT NULL DEFAULT '0' AFTER `rights`;
Получаем такую вот структуру:



2 Тег input для почты

Тоже все просто:

<input requred name="email" type="email" size="50" placeholder="email" />
3 Вставка email

Наверно надо было сразу написать, ну да ладно, можно и сейчас. Дело в том, что мы модифицируем уже имеющийся скрипт; у вас может быть другая схема, но все же в большинстве случаев шаги могут быть именно такими. Так что не стоит бездумно копировать код, я просто пишу ход решения, а строки кода – это как бы иллюстрация реализации, не более.

Здесь у нас обычное подключение (расширение драйвера) MySQLi. Модифицируем функцию добавления пользователя таким образом:

function addNewUser($login, $password, $role, $email){
    global $link;
    $query = "INSERT INTO `users` (`id`,`login`,`password`,`rights`,`email`,`reset_token`) VALUES (NULL,'$login','$password','$role','$email','0');";
    
    $result = mysqli_query($link, $query) or die (mysqli_error($link)); 
    $id = mysqli_insert_id($link);
    return $id;
}
Обращаю внимание, что перед вставкой надо либо проверить на sql-иньекцию вводимые поля, либо же использовать параметризованный запрос, что-то типа mysqli_stmt_bind_param. 4 Форма для ввода email

Громко звучит – форма, на самом деле одно поле + кнопка отправки. Что-то типа такого наваяем:

<form action="<?php echo $form_action; ?>" method="POST">
    <p>Введите email, на который будет отправлена ссылка для сброса пароля</p>
    <p><input requred name="email" type="email" size="30" placeholder="email" 
    <p>Введите новый пароль</p>
    <p><input requred name="password" type="password" size="30" placeholder="пароль" /></p>
    <p><input class="btn btn-success pull-right" type="submit" value="Отправить"/></p>
</form> 
5 Проверка, отправка письма

После того, как пользователь введет свой email и нажмет кнопку «Отправить»

If( !checkUserEmail($email)){
echo "пользователь с таким email не найден в базе данных!";	}
else {
	//создаем токен и записываем его в базу данных
	$reset_token = hash('sha384', time().$email.);
	updateRow("users", "reset_token", $reset_token, "email", $email);

	//формируем ссылку для сброса пароля
	$href = $site."/reset.php?reset_token=".$reset_token."&email=".$email;

	//формируем письмо
    	$subject = 'Сброс пароля';
    	$message = "Для сброса пароля перейдите по ссылке $href";
    	$headers = 'From: qwerty@mail.ru'       . "\r\n" .
                 'Reply-To: wqerty@mail.ru' . "\r\n" .
                 'X-Mailer: PHP/' . phpversion();

		//отправляем письмо
    	if (mail($email, $subject, $message, $headers)
6 Форма для нового пароля

<form action="<?php echo $form_action; ?>" method="POST">
    <p>Введите новый пароль</p>
    <p><input requred name="password" type="password" size="30" placeholder="пароль" /></p>
    <p><input class="btn btn-success pull-right" type="submit" value="Отправить"/></p>
</form> 
7 Меняем пароль на новый

if (isset($_GET["reset_token"]) && isset($_GET["email"])){
    $reset_token = $_GET["reset_token"];
    $email = $_GET["email"];
    $form_action = $form_action."?reset_token=$reset_token&email=$email";

    //проверяем токен и почту
    if (!$reset_token){
        $err ="ошибка";
        echo "<div class='alert alert-danger alert-dismissible fade show' role='alert'>$err
        <button type='button' class='close' data-dismiss='alert' aria-label='Close'>
        <span aria-hidden='true'>×</span>
      </button>
      </div>";
    }else {
        $uid = getUserIdFromResetToken($reset_token, $email);

        if ($uid <=0){
            $err ="ошибка";
            echo "<div class='alert alert-danger alert-dismissible fade show' role='alert'>$err
            <button type='button' class='close' data-dismiss='alert' aria-label='Close'>
            <span aria-hidden='true'>×</span>
          </button>
          </div>";
        }

        else if (isset($_POST["password"])){
            $password = $_POST["password"];
            $err2 = checkUserPassword($password);

            //проверяем пароль
            if ($err2){
                echo "<div class='alert alert-danger alert-dismissible fade show' role='alert'>
                Ошибки пароля: $err2
                <button type='button' class='close' data-dismiss='alert' aria-label='Close'>
                <span aria-hidden='true'>×</span>
              </button>
              </div>";
            }
            else{
                //обнуляем токен и меняем пароль в базе
                updateRow("users", "reset_token", '0', "email", $email);
                updateRow("users", "password", $password, "email", $email);
}
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.



тегизаметки, php, пароли




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.



Урок 2. Комментарии JavaScript
Две семьи
Максимальный id в SQLite