Восстановлени пароля пользователя php + mysq

Восстановлени пароля пользователя php + mysq

Привет друзья. В самом начале создания своего блога я написал статью как создать регистрацию и авторизацию на PHP + MySQL. Данная статья стала очень актуальной на моем блоге и требует своего логического продолжения, а именно это восстановление пароля пользователя. Ища информацию на просторах Рунета вы много найдете статей как создать регистрацию и авторизацию пользователей на сайте, но при этом все опускают тот момент, когда пользователь забыл свой пароль. В данной статье мы исправим этот досадный момент.

Восстановление пароля пользователя может быть двух способов:

  • Когда пароль в базе данных хранится не в зашифрованном виде, то вы можете выслать данный пароль пользователю на его email. (Хранить пароли в открытом виде очень небезопасно и так делать нельзя!).
  • Второй вариант, когда пароль хранится в зашифрованном виде, например, по средствам md5() и возможность дешифровать его нет. Тогда нужно создавать новый пароль и обновлять запись в таблице.

Рассмотрим структуру нашей таблицы:

Таблица bez_reg

У нас есть ID, есть логин, пароль в зашифрованном виде с солью, соль, active_hex и статус пользователя. Исходя из этих данных будем создавать алгоритм восстановления пароля на сайте. Особое внимание нужно уделить полю active_hex так как оно будет непосредственно участвовать в восстановлении пароля пользователя.

Сейчас попробуем описать алгоритм действий для реализации восстановления пароля пользователя на php + mysql.

  • Показываем форму с вводом логина для восстановления.
  • Если такой логин есть, то шлем ему письмо ссылкой и ключом в качестве ключа используем строку из ячейки active_hex.
  • Когда пользователь прошел по ссылке проверяем ключ, если ключ совпадает с полем active_hex то выводим форму с двумя полями для вода нового пароля. Как только пользователь сменил пароль, в целях безопасности генерируем новый active_hex, чтобы никто не смог воспользоваться ссылкой восстановления пароля повторно! Далее отправляем письмо о том, что пароль сменен и ссылку для входа.
  • Пользователь входит с новым паролем.

Я не буду здесь расписывать все скрипты, вы можете ознакомится с ними в первой статье регистрация и авторизация на PHP + MySQL. Здесь я выложу дополнения к данным скриптам.

В каталоге scripts создаем новую папку reminder. В данном каталоге создаем три файла:

  • form_reminder.html
  • new_pass_form.html
  • reminder.php

Структура каталогов регистрация и авторизация php + mysql

Далее переходим в index.php и подключаем наши файлы в switch();

<?php
    /**
    * Главный файл (переключатель)
    * Site: http://bezramok-tlt.ru
    * Регистрация пользователя письмом
    */

    //Запускаем сессию
    session_start();

    //Устанавливаем кодировку и вывод всех ошибок
    header('Content-Type: text/html; charset=UTF8');
    error_reporting(E_ALL);

    //Включаем буферизацию содержимого
    ob_start();

    //Определяем переменную для переключателя
    $mode = isset($_GET['mode'])  ? $_GET['mode'] : false;
    $user = isset($_SESSION['user']) ? $_SESSION['user'] : false;
    $err = array();


    //Устанавливаем ключ защиты
    define('BEZ_KEY', true);
     
    //Подключаем конфигурационный файл
    include './config.php';
     
    //Подключаем скрипт с функциями
    include './func/funct.php';

    //подключаем MySQL
    include './bd/bd.php';

    switch($mode)
    {
        //Подключаем обработчик с формой регистрации
        case 'reg':
            include './scripts/reg/reg.php';
            include './scripts/reg/reg_form.html';
        break;
        
        //Подключаем обработчик с формой авторизации
        case 'auth':
            include './scripts/auth/auth.php';
            include './scripts/auth/auth_form.html';
            include './scripts/auth/show.php';
        break;

        //Восстановление пароля
        case 'reminder';
            include './scripts/reminder/reminder.php';
            //Выводим нужную форму для пользователя
            //Проверяем что ключ не проходит по ссылке после востановления
            if(isset($_GET['key']))
            {
                //Проверяем есть ли такой ключ
                $sql = 'SELECT COUNT(*) AS `total`
                        FROM `'. BEZ_DBPREFIX .'reg`
                        WHERE `active_hex` = :active_hex';

                //Подготавливаем PDO выражение для SQL запроса
                $stmt = $db->prepare($sql);
                $stmt->bindValue(':active_hex', $_GET['key'], PDO::PARAM_STR);
                if($stmt->execute())
                {
                    $row = $stmt->fetch(PDO::FETCH_ASSOC);

                    //Проверяем что вернул запрос
                    if($row['total'] == 0)
                        include './scripts/reminder/form_reminder.html';
                    else
                    {
                        //Отправляем на главную страницу
                        //header('Location: '. BEZ_HOST);
                        //exit;
                        include './scripts/reminder/new_pass_form.html';
                    }
                }
            }
            else
            {
                if(!isset($_GET['newpass']))
                    include './scripts/reminder/form_reminder.html';
            //  include './scripts/reminder/new_pass_form.html';
            }
        break;
    
    }
    
    //Получаем данные с буфера
    $content = ob_get_contents();
    ob_end_clean();

    //Подключаем наш шаблон
    include './html/index.html';
?>           

Создаем html разметку для формы восстановления пароля пользователя в файле form_reminder.html

<div class="col-md-8 col-md-offset-2"> 
<div class="panel panel-primary">
  <div class="panel-heading"><h4>Восстановление параметров авторизации</h4></div>
  <div class="panel-body">
    <p>Если забыли свои параметры авторизации, не переживайте, их можно восстановить. Для этого введите, пожалуйста, ниже свой email.</p>
    <form class="form-horizontal" action="" method="POST">
  <div class="form-group">
    <label for="inputEmail" class="col-xs-2 control-label">Адрес email:</label>
    <div class="col-xs-10">
     <input type="email" class="form-control" id="inputEmail" name="email" placeholder="Введите email">
    </div>
  </div>
 <div class="form-group">
    <div class="col-xs-offset-2 col-xs-10">
      <button type="submit" class="btn btn-primary" name="reminder">Восстановить</button>
   </div>
  </div>
</form>
  </div>
</div>
</div>

Далее создаем html разметку для ввода нового пароля пользователя в файле new_pass_form.html

<div class="col-md-8 col-md-offset-2"> 
<div class="panel panel-primary">
  <div class="panel-heading"><h4>Восстановление пароля</h4></div>
  <div class="panel-body">
    <form class="form-horizontal" action="" method="POST">
  <div class="form-group">
    <label for="inputPass" class="col-xs-2 control-label">Пароль:</label>
    <div class="col-xs-10">
     <input type="password" class="form-control" id="inputPass" name="pass" placeholder="Введите пароль">
    </div>
  </div>
    <div class="form-group">
    <label for="inputPass2" class="col-xs-2 control-label">Повторите пароль:</label>
    <div class="col-xs-10">
     <input type="password" class="form-control" id="inputPass2" name="pass2" placeholder="Введите подтверждение пароля">
    </div>
  </div>
 <div class="form-group">
    <div class="col-xs-offset-2 col-xs-10">
      <button type="submit" class="btn btn-primary" name="newPass">Изменить</button>
   </div>
  </div>
</form>
  </div>
</div>
</div>

Формы мы сделали, самое время написать обработчик данных форм reminder.php

<?php
 /**
 * Обработчик формы восстановления пароля
 * Site: http://bezramok-tlt.ru
 * Авторизация пользователя
 */

 //Ключ защиты
 if(!defined('BEZ_KEY'))
 {
     header("HTTP/1.1 404 Not Found");
     exit(file_get_contents('./../404.html'));
 }
 
 //Выводим сообщение об отправки ссылки для восстановления пароля
 if(isset($_GET['send']) and $_GET['send'] == 'ok')
    echo '<div class="alert alert-success"><h4 class="text-center">Ваш запрос на восстановление пароля отправлен на указаный вами email!</h4></div>';

  //Выводим сообщение об успешно смене пароля
  if(isset($_GET['newpass']) and $_GET['newpass'] == 'ok')
    echo '<div class="alert alert-success"><h4 class="text-center">Ваш пароль успешно изменен, проверьте свой email!</h4></div>';

 //Если нажата кнопка восстановить пароль утюжим переменные 
 if(isset($_POST['reminder'])){
    
    //Если email существует, то проверяем есть ли он в нашей базе
    if(emailValid($_POST['email'])){
        //Запрос на выборку аккаунта для восстановления
        $sql = 'SELECT * FROM `'. BEZ_DBPREFIX .'reg`
                WHERE `status` = 1
                AND `login` = :email';

        //Подготавливаем PDO выражение для SQL запроса
        $stmt = $db->prepare($sql);
        $stmt->bindValue(':email', $_POST['email'], PDO::PARAM_STR);
        if($stmt->execute())
        {
            //Получаем ответ от MySQL
            $rows = $stmt->fetch(PDO::FETCH_ASSOC);
            
            //Проверяем что такой email есть
            if(!empty($rows))
            {
                //Шлем письмо для восстановления пароля
                $title = 'Вы запросили восстановление пароля на http://bezramok-tlt.ru';
                $message = 'Для смены пароля Вам нужно пройти по ссылке <a href="'. BEZ_HOST .'?mode=reminder&key='. $rows['active_hex'] .'">'. BEZ_HOST .'?mode=reminder&key='. $rows['active_hex'] .'</a>';
                    
                sendMessageMail($_POST['email'], BEZ_MAIL_AUTOR, $title, $message);
                    
                //Перенаправляем пользователя на нужную нам страницу
                header('Location:'. BEZ_HOST .'?mode=reminder&send=ok');
                exit;
            }
            else
            {
                echo showErrorMessage('Нет такого пользователя!');
            }
        }
        else
        {
                echo showErrorMessage('Чтото пошло не так :(');
        }

    }
    else
    {
        echo showErrorMessage('Не верные данные!');
    }

}

 //Если пользователь сменил пароль
if(isset($_POST['newPass']))
{
    //Утюжим переменные
    if(empty($_POST['pass']))
        $err[] = 'Поле Пароль не может быть пустым';
    
    if(empty($_POST['pass2']))
        $err[] = 'Поле Подтверждения пароля не может быть пустым';
    
    //Проверяем равенство паролей
    if($_POST['pass'] != $_POST['pass2'])
        $err[] = 'Пароли не совподают!';
    
    //Проверяем наличие ошибок и выводим пользователю
    if(count($err) > 0)
        echo showErrorMessage($err);
    else
    {
        //Получаем данные о пользователе
        $sql = 'SELECT * FROM `'. BEZ_DBPREFIX .'reg`
                WHERE `status` = 1
                AND `active_hex` = :active_hex';

        //Подготавливаем PDO выражение для SQL запроса
        $stmt = $db->prepare($sql);
        $stmt->bindValue(':active_hex', $_GET['key'], PDO::PARAM_STR);
        if($stmt->execute())
        {
            //Получаем ответ от MySQL
            $rows = $stmt->fetch(PDO::FETCH_ASSOC);
            
            //Почтовый ящик
            $email = $rows['login'];
            
            //Солим пароль
            $pass = md5(md5($_POST['pass']).$rows['salt']);
            
            //Создаем новый active_hex для защиты
            $active_hex = md5($pass);

            //Обновляем данные в таблице
            $sql = 'UPDATE `'. BEZ_DBPREFIX .'reg`
                SET 
                    `pass` = :pass, 
                    `active_hex` = :active_hex
                WHERE `id` = '. $rows['id'];
            
            //Подготавливаем PDO выражение для SQL запроса
            $stmt = $db->prepare($sql);
            
            //Если запрос выполнился
            if($stmt->execute(array(':pass' => $pass, ':active_hex' => $active_hex)))
            {
                //Отправляем сообщение на почту об успешной смене пароля
                $title = 'Вы успешно сменили пароль на http://bezramok-tlt.ru';
                $message = 'Вы успешно сменили пароль на '. $_POST['pass'] .'
                <p>для входа в систему перейдите по ссылке <a href="'. BEZ_HOST .'?mode=auth">'. BEZ_HOST .'?mode=auth</a></p>';
                        
                sendMessageMail($email, BEZ_MAIL_AUTOR, $title, $message);
                    
                //Перенаправляем пользователя на нужную нам страницу
                header('Location:'. BEZ_HOST .'?mode=reminder&newpass=ok');
                exit;
            }

        }
    }
    
}

?>

Как видите написание данного функционала совсем не сложное дело, проблема в том, что новички в программирование не могут выразить человеческим языком последовательность действий (алгоритма работы), тем самым и создаются трудности в написании того или иного скрипта. С вами был админ https://bezramok-tlt.ru до новых встреч друзья и удачного кодинга!

Архив перезалил: 02.02.2017г.

Скачать: Восстановлени пароля пользователя php + mysq


Поддержи проект:

  • ...
    Андрей 20:44:36 12/08/2017
    Еще такой вопрос, я добавил в сессию ID пользователя после
    $_SESSION['user'] = true;
    
    добавил
    $_SESSION['user_id'] = $rows[0]['id'];
    
    я так понимаю сессия должна работать на всех страницах на вашей странице Index.php - user_id работает
    Array(
    [user] => 1
    [user_id] => 4
    )
    
    я перехожу на другую страницу с кодом:
    if(!$_SESSION['user'] = true)
    { header('Location:'. BEZ_HOST .'user/?mode=auth'); }
    else
    {
      echo "Вы авторизированы<br><br><br><pre>";
      print_r($_SESSION);
      echo "</pre>";
    }
    
    и на ней user_id куда-то теряется
    Array(
    [user] => 1
    )
    
    Что это может быть? Спасибо!
  • Администрация
    Администрация 18:10:31 29/08/2017

    У Вас ошибка в условии if(!$_SESSION['user'] = true)  должен стоять оператор сравнения ==

  • ...
    Андрей 19:39:43 12/08/2017
    Я так понимаю при смене пароля как-то не корректно отправляется письмо. обратный адрес BEZ_MAIL_AUTOR  в письмо не попадает, присьмо приходит без обратного адреса и попадает в спам. Попробую найт ошибку, может вы найдете ее быстрее. Спасибо.
  • Администрация
    Администрация 18:05:28 29/08/2017

    Так как сервер ваш или арендованный у хостера, я не смогу ничем помочь. Т.к. в СПАМ письмо уходит благодаря фильтру почтового сервиса, например маил.ру

  • ...
    Андрей 21:17:23 09/08/2017
    Письмо с ссылкой для подтверждения регистрации, и после этого письмо о благополучной регистрации - приходит А восстановление пароля - нет Вот что удивительно. Я на почтовом ящике гугля тестирую
  • Администрация
    Администрация 21:21:13 09/08/2017

    Ради эксперимента заведите почту другого сервиса маил или яндекс, посмотрите как к ним будут приходить письма. 

  • ...
    Андрей 17:18:01 08/08/2017
    Я перешел по ссылке, открылась форма смены пароля, пароль поменял, все нормально, подтверждение измененного пароля письмо пришло, но тоже криво и тоже в спам.
  • Администрация
    Администрация 10:45:02 09/08/2017

    По поводу писем обратитесь к хостеру. Скорей всего ваш почтовый сервис использует фильтр, по этому письма попадают в спам.

  • ...
    Андрей 17:14:04 08/08/2017
    Да, в спаме, как-то криво приходит, может что-то поправить? A message that you sent contained no recipient addresses, and therefore no delivery could be attempted. ------ This is a copy of your message, including all the headers. ------ To: Subject: =?utf-8?b?0JLRiyDQt9Cw0L/RgNC+0YHQuNC70Lgg0LLQvt1?= Content-type: text/html; charset="utf-8" From: Регистрация на МОЙДОМЕН MIME-Version: 1.0 Date: Tue, 08 Aug 2017 05:08:54 +0300 Message-Id:
  • Администрация
    Администрация 10:43:17 09/08/2017

    Это вам нужно к хостеру вашему обратиться.

Форма обратной связи
captcha
Случайные статьи: