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

Восстановлени пароля пользователя 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


Теги

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


...
Владимир
Привет, админ С Новым Годом! Можно ли пожалуйста, подсказать что мне надо изменить что бы при активации акаунта, этот пользователь становился а онлайн? А то получается что сперва надо активировать акк, а потом аж надо заходить на сайт,  под своим логином и паролем, это не удобно как то. Жду вашего предложения что и как сделать.

03/01/2017 00:55:08

Администрация
Администрация

Во время активации, вы можете установить нужные сессионые переменны для того чтобы пользователь был залогинен, далее редиректом отправляете на главную страницу уже залогиненного пользователя.

02/02/2017 13:25:09

...
я заметил
Админ думаю что ты знаешь кто я )))) Меня тоже интересует вот данная тема: От Владимира: Протестировал, вроде все нормально, только нет предупреждения, что такое восстановления было. Ну или не перенаправлять если ссылка уже использовалась эта. А если только что пришла тогда перенаправлять его. Если можете подскажите как такое учудить. Или просто добавить как эта ссылка уже использовалась ранее вами. Пожалуйста пройдите по той ссылке что пришла только что. Хочу сразу эту поправку сделать, что бы не было такой ошибки.

28/12/2016 12:29:22

Администрация
Администрация

Готово. Можешь скачать новый архив )

02/02/2017 13:25:45

...
RachelPield
Новый XRumer 16.0 - революция в интернет продвижении: искусственный интеллект поможет Вам в привлечении клиентов столь эффективно, как никогда!

24/12/2016 01:18:09

Администрация
Администрация

RachelPield - меня данный способ не интересует.

24/12/2016 10:03:13

...
Александр
В файл где регистрация, вход, там я добавил строчку  <li><a href="<?php echo BEZ_HOST; ?>?mode=reminder">Забыли пароль?</a></li>  и включил два файла как в вашем примере в index.php 

13/12/2016 04:03:34

Администрация
Администрация

Да все правильно. По поводу что не приходят письма я вам ответил.

14/12/2016 21:12:34

...
Александр
На почту письмо не отправляется, хотя пишет, что было отправлено

13/12/2016 03:21:21

Администрация
Администрация

По поводу email отвечал кучу раз, все дело в бесплатном хостинге, если хост платны, то проблемы могут быть с настройками на стороне хостинга ( была у меня такая ситуация), возможно письмо попало в СПАМ. Если вы используете локальный сервер типа ДЕНВЕР или чтото другое, то они почту не могут отправлять!!! У данных приложений есть заглушка sendmail ищите в ней ваше письмо!

14/12/2016 21:09:45

...
Владимир
Протестировал, вроде все нормально, только нет предупреждения, что такое восстановления было. Ну или не перенаправлять если ссылка уже использовалась эта. А если только что пришла тогда перенаправлять его. Если можете подскажите как такое учудить. Или просто добавить как эта ссылка уже использовалась ранее вами. Пожалуйста пройдите по той ссылке что пришла только что.

10/12/2016 00:30:32

Администрация
Администрация

Спасибо за ваши пожелания. Я подумаю над этим. Но как уже писал, все после нового года.

14/12/2016 21:02:52

...
Владимир
Админ ну как изменили файл? Все же жду его)

10/12/2016 00:08:52

Администрация
Администрация

До нового года точно не выложу, горит проект. Так что сорри друзья.

14/12/2016 21:01:23

...
Николай
Админ я тестировал восстановления пароля и заметил одну погрешность. Если человек восстанавливает пароль, потом изменяет пароль и подтверждает его сам пароль изменяется и в базу записывается новые данные для пароля но: Если он опять нажмет на восстановления пароля ссылка придет ему, но если он перейдет не по этой ссылке которая пришла только что, а по той что была первая ему откроется форма для изменения пароля и он так же может через первую ссылку восстановить пароль. Исправьте эту погрешность или напишите в комментариях где надо добавить кусок того чего не хватает, СПАСИБО.

06/12/2016 10:30:20

Администрация
Администрация

Нужно немного поменять логику скрипта, чуть позже выложу, сейчас нет времени. Спасибо что заметили и сообщили.

08/12/2016 14:36:22

...
Николай
Админ спасибо. Я протестировал тоже все меняется. Отлично.

20/11/2016 23:22:22

Администрация
Администрация

Ок. )

21/11/2016 08:24:13

...
Николай
Привет, админ... Я заметил погрешность в вашем скрипте на восстановления пароля. Заключается в том что: Когда восстанавливаешь пароль то в базе не меняется данные в salt ну и в pass, пароль как бы и остается тем же как и был в базе не подставляет другие значения данные не меняются от них. Как исправить? В скрипт config что то менять или что?

12/11/2016 17:48:45

Администрация
Администрация

Николай при восстановлении меняются два параметра в таблице это сам пароль и active_hex обновлять соль в таблице не имеет практического смысла.

По поводу того что данные не меняются. Только что проверял, все меняется ниже SQL запрос который обновляет pass и active_hex

//Обновляем данные в таблице
$sql = 'UPDATE `'. BEZ_DBPREFIX .'reg`
		SET 
		`pass` = :pass, 
		`active_hex` = :active_hex
		WHERE `id` = '. $rows['id'];

13/11/2016 10:16:26


Copyright © 2014 - 2021 All rights reserved.