Привет друзья. В самом начале создания своего блога я написал статью как создать регистрацию и авторизацию на PHP + MySQL . Данная статья стала очень актуальной на моем блоге и требует своего логического продолжения, а именно это восстановление пароля пользователя . Ища информацию на просторах Рунета вы много найдете статей как создать регистрацию и авторизацию пользователей на сайте, но при этом все опускают тот момент, когда пользователь забыл свой пароль. В данной статье мы исправим этот досадный момент.
Восстановление пароля пользователя может быть двух способов:
- Когда пароль в базе данных хранится не в зашифрованном виде, то вы можете выслать данный пароль пользователю на его email. (
Хранить пароли в открытом виде очень небезопасно и так делать нельзя!
).- Второй вариант, когда пароль хранится в зашифрованном виде, например, по средствам md5() и возможность дешифровать его нет. Тогда нужно создавать новый пароль и обновлять запись в таблице.
У нас есть ID, есть логин, пароль в зашифрованном виде с солью, соль, active_hex и статус пользователя. Исходя из этих данных будем создавать алгоритм восстановления пароля на сайте. Особое внимание нужно уделить полю active_hex так как оно будет непосредственно участвовать в восстановлении пароля пользователя.
Сейчас попробуем описать алгоритм действий для реализации восстановления пароля пользователя на php + mysql.
- Показываем форму с вводом логина для восстановления.
- Если такой логин есть, то шлем ему письмо ссылкой и ключом в качестве ключа используем строку из ячейки active_hex.
- Когда пользователь прошел по ссылке проверяем ключ, если ключ совпадает с полем active_hex то выводим форму с двумя полями для вода нового пароля. Как только пользователь сменил пароль, в целях безопасности генерируем новый active_hex, чтобы никто не смог воспользоваться ссылкой восстановления пароля повторно! Далее отправляем письмо о том, что пароль сменен и ссылку для входа.
- Пользователь входит с новым паролем.
Я не буду здесь расписывать все скрипты, вы можете ознакомится с ними в первой статье регистрация и авторизация на PHP + MySQL . Здесь я выложу дополнения к данным скриптам.
- form_reminder.html
- new_pass_form.html
- reminder.php
<?php
/**
* Главный файл (переключатель)
* Site: https://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';
?>
<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>
<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>
<?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г.
03/01/2017 00:55:08
28/12/2016 12:29:22
13/12/2016 04:03:34
13/12/2016 03:21:21
По поводу email отвечал кучу раз, все дело в бесплатном хостинге, если хост платны, то проблемы могут быть с настройками на стороне хостинга ( была у меня такая ситуация), возможно письмо попало в СПАМ. Если вы используете локальный сервер типа ДЕНВЕР или чтото другое, то они почту не могут отправлять!!! У данных приложений есть заглушка sendmail ищите в ней ваше письмо!
14/12/2016 21:09:45
10/12/2016 00:30:32
06/12/2016 10:30:20
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