Сценарий восстановления пароля

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

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

Введение

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

sourse

Для нешифруемых паролей мы создадим шаблонное электронное письмо и будем отправлять пользователю его пароль по указанному при регистрации адресу.

С шифруемыми паролями дела обстоят немного сложнее. Когда пароль зашифровывается с помощью функции md5(), он не может быть расшифрован. По этой причине мы будем отправлять пользователю ссылку, пройдя по которой он сможет изменить пароль. Чтобы обезопасить данный процесс, мы будем пользоваться уникальным ключом, который будет проверяться при возврате пользователя на страницу аутентификации. Чтобы улучшить защиту, мы будем применять технологию прибавления соли к шифруемому паролю.

ВАЖНО: в данном уроке мы используем MySQLi вместо MySQL. Несмотря на то что в документации по PHP утверждается, что все должно работать корректно, у меня возникали проблемы с использованием классов MySQLi, пока я не обновил версию 5.1.4 до 5.2.9. Если у вас возникнут ошибки, связанные с использованием неподдерживаемого буффера (‘unsupported buffer’), попробуйте обновить PHP. В случае, если возникнут ошибки о ненахождении класса mysqli, вам также может понадобится изменить файл php.ini, чтобы загрузить расширение mysqli.

В зависимости от того, шифруемые или нешифруемые пароли используются на вашем сайте, придется следовать разным указаниям. В общем, инструкции касаются шифруемых паролей, но кое-где будут примечания о нешифруемых паролях.

Шаг 1. Таблицы базы данных

После создания новой базы данных, нам нужно создать три таблицы:

В таблице recoveryemails_enc хранится информация об электронных письмах, которые будут отправляться пользователям для изменения пароля (секретный код, идентификатор пользователя и срок действия). Таблица users содержит информацию о пользователях. Если пароли на вашем сайте зашифровываются, используйте таблицу users_enc, иначе таблицу users.

Если у вас уже есть таблица пользователей, вам понадобится добавить поля секретного вопроса и ответа. Поле с вопросом будет содержать целочисленное значение, которое приравнивает секретный вопрос к массиву. Тип значения поля с ответом — текстовый (varchar). Секретный вопрос используется в качестве контроля перед отправкой электронного письма с паролем. Вот код создания таблиц (файл sql.txt доступен для загрузки).

CREATE TABLE IF NOT EXISTS `recoveryemails_enc` (
  `ID` bigint(20) unsigned zerofill NOT NULL auto_increment,
  `UserID` bigint(20) NOT NULL,
  `Key` varchar(32) NOT NULL,
  `expDate` datetime NOT NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `users` (
  `ID` bigint(20) unsigned zerofill NOT NULL auto_increment,
  `Username` varchar(20) NOT NULL,
  `Email` varchar(255) NOT NULL,
  `Password` varchar(20) NOT NULL,
  `secQ` tinyint(4) NOT NULL,
  `secA` varchar(30) NOT NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `users` (`ID`, `Username`, `Email`, `Password`, `secQ`, `secA`) VALUES (00000000000000000002, 'jDoe', 'jDoe@gmail.com', 'johnDoe2009', 0, 'Smith'),
(00000000000000000003, 'envato', 'webmaster@envato.com', 'envatouser', 1, 'Sydney'),
(00000000000000000004, 'sToaster', 'toast@yahoo.com', 'toastrules', 3, '2001');
CREATE TABLE IF NOT EXISTS `users_enc` (
  `ID` bigint(20) unsigned zerofill NOT NULL auto_increment,
  `Username` varchar(20) NOT NULL,
  `Password` char(32) NOT NULL,
  `Email` varchar(255) NOT NULL,
  `secQ` tinyint(4) NOT NULL default '0',
  `secA` varchar(32) NOT NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
INSERT INTO `users_enc` (`ID`, `Username`, `Password`, `Email`, `secQ`, `secA`) VALUES (00000000000000000001, 'jDoe', 'fd2ba57673c57ac5a0650c38fe60b648', 'jDoe@gmail.com', 0, 'Smith'),
(00000000000000000002, 'envato', '1ecc663314777c8e3c2328027447f194', 'webmaster@envato.com', 1, 'Sydney'),
(00000000000000000003, 'sToaster', 'e05fd29cbca7ea9add48ba6dafc300e8', 'toast@yahoo.com', 3, '2001');

Шаг 2. Подключение базы данных

Нам необходимо создать файл для подключения базы данных. Для взаимодействия с базой данных мы будем использовать MySQLi, которая обеспечивает объектно-ориентированный подход к взаимодействию с базами данных. Создайте файл assets/php/database.php. Вставьте данный код (измените значения переменных на подходящие вашему хостингу):

<?php
session_start();
ob_start();
$hasDB = false;
$server = 'localhost';
$user = 'user';
$pass = 'password';
$db = 'db';
$mySQL = new mysqli($server,$user,$pass,$db);
if ($mySQL->connect_error)
{
    die('Connect Error (' . $mySQL->connect_errno . ') '. $mySQL->connect_error);
}
?>

В первой строке кода мы вызываем функцию session_start(). В действительности, мы не будем использовать переменные сессии, но вам понадобится сессия как часть системы входа пользователя на сайт. Затем мы вызываем функцию ob_start() для запуска буфера вывода.

Строки 4-8 устанавливают переменные для соединения с сервером. Затем создаем новый объект mysqli, передав ему наши переменные. Для оставшейся части кода $mySQL позволит взаимодействовать с базой данных как требуется.

MySQLi обрабатывает ошибки немного иначе, поэтому нам необходимо проверять свойство connect_error после подключения и выводить сообщение об ошибке в случае, если что-то пошло не так. То же самое касается создания запросов. Для обнаружения ошибок необходимо проверять свойство error нашего запроса или объекта соединения.

Шаг 3. Создание страницы восстановления пароля

Давайте начнем с создания файла forgotPass.php. Добавим следующий код:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Password Recovery</title>
<link href="assets/css/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="header"></div>
<div id="page">
<!--PAGE CONTENT-->
</div>
</body>
</html>

Этот html код будет хорошей основой. Вот результат:

Затем вставьте следующий код в самое начало только что созданного файла:

<?php
include("assets/php/database.php");
include("assets/php/functions.php");
$show = 'emailForm'; // какую стадию отображать по молчанию
if ($_SESSION['lockout'] == true && (mktime() > $_SESSION['lastTime'] + 900))
{
	$_SESSION['lockout'] = false;
	$_SESSION['badCount'] = 0;
}
if (isset($_POST['subStep']) && !isset($_GET['a']) && $_SESSION['lockout'] != true)
{
	switch($_POST['subStep'])
	{
		case 1:
			// отправляем электронный адрес или имя пользователя
			$result = checkUNEmail($_POST['uname'],$_POST['email']);
			if ($result['status'] == false )
			{
				$error = true;
				$show = 'userNotFound';
			} else {
				$error = false;
				$show = 'securityForm';
				$securityUser = $result['userID'];
			}
		break;
		case 2:
			// отправляем секретный вопрос
			if ($_POST['userID'] != "" && $_POST['answer'] != "")
			{
				$result = checkSecAnswer($_POST['userID'],$_POST['answer']);
				if ($result == true)
				{
					// ответ верен
					$error = false;
					$show = 'successPage';
					$passwordMessage = sendPasswordEmail($_POST['userID']);
					$_SESSION['badCount'] = 0;
				} else {
					// ответ неверен
					$error = true;
					$show = 'securityForm';
					$securityUser = $_POST['userID'];
					$_SESSION['badCount']++;
				}
			} else {
				$error = true;
				$show = 'securityForm';
			}
		break;
		case 3:
			// отправляем новый пароль (для случая с шифруемыми паролями)
			if ($_POST['userID'] == '' || $_POST['key'] == '') header("location: login.php");
			if (strcmp($_POST['pw0'],$_POST['pw1']) != 0 || trim($_POST['pw0']) == '')
			{
				$error = true;
				$show = 'recoverForm';
			} else {
				$error = false;
				$show = 'recoverSuccess';
				updateUserPassword($_POST['userID'],$_POST['pw0'],$_POST['key']);
			}
		break;
	}
}

В первую очередь мы подключаем файл создания базы данных и файл с функциями, который мы вскоре создадим. Затем мы создаем переменную $show, которая устанавливает, какой элемент интерфейса отображать. По умолчанию будет отображаться форма введения электронного письма.

После этого мы проверяем некоторые переменные сессии. Если переменная сессии lockout = true, и со времени блокировки прошло больше 900 секунд (15 минут), мы завершим блокировку (строки 7 и 8).

Затем создадим if-блок, в котором будет проверяться, передано ли что-либо на страницу. Мы также должны удостовериться в том, что $_GET[‘a’] не установлена. Эта переменная будет установлена, когда пользователь перейдет по ссылке, отправленной ему в письме восстановления пароля. Итак, если это происходит, мы можем пропустить проверку передачи данных на страницу. В этом же логическом блоке мы должны удостовериться в том, что переменная блокировки не установлена в true.

Сразу после блока if с помощью switch($_POST[‘subStep’]) мы проверяем, на какой стадии формы данные были отправлены. Нам необходимо будет обрабатывать три стадии. Первая стадия означает, что мы ввели только логин или адрес электронной почты для изменения пароля. Для этого мы вызываем функцию checkUNEmail(), которую мы вскоре напишем. Эта функция возвращает массив со значением boolean для установки, найден ли пользователь, и целочисленное значение с идентификатором пользователя, если он найден. В строке 17 проверяется, был ли найден пользователь, если нет, мы устанавливаем флаг ошибки и переменную $show, чтобы отобразить сообщение об ошибке ‘Пользователь не найден’. Если пользователь найден, нам следует отобразить форму с секретным вопросом и установить переменную $securityUser, чтобы узнать, для какого пользователя загружать вопрос.

На второй стадии мы отправили секретный вопрос. В первую очередь мы проверяем, возвращены ли идентификатор пользователя и ответ на вопрос. Если хотя бы одно из полей не было заполнено, мы снова отображаем форму с секретным вопросом. Если оба значения получены, вызываем функцию, которая сверит значения со введенными в базу данными. Эта функция возвращает обычное значение boolean. Если на вопрос отетили правильно, отобразится страница с сообщением об успехе, отправится электронное письмо и установим в 0 переменную подсчета неуспешных вводов. Если на вопрос ответили неверно, мы снова отображаем страницу с вопросом и инкриминтируем значение переменной неуспешных вводов ответа.

Третья стадия начинается, когда пользователь получил письмо восстановления пароля, перешел по ссылке и заполнил форму с новым паролем. Во-первых, если пользовательский идентификатор или секретный код не получен, загружается главная страница. Затем мы проверяем, совпадают ли оба введенных пароля и введены ли они вообще. Если пароли не совпадают, форма загружается заново. Если же они совпадают, отображается сообщение о том, что все произошло успешно, и вызывается функция изменения пароля пользователя.

ПРИМЕЧАНИЕ: если вы используете вариант с нешифруемыми паролями, вы можете упустить третью стадию, описанную выше. Это метод, который сохраняет новый введенный пароль. Мы можем отправить незашифрованный пароль в письме, так как пользователю нет необходимости его изменять.

Теперь необходимо добавить следующий код в блок if, написанный выше:

elseif (isset($_GET['a']) && $_GET['a'] == 'recover' && $_GET['email'] != "") {
	$show = 'invalidKey';
	$result = checkEmailKey($_GET['email'],urldecode(base64_decode($_GET['u'])));
	if ($result == false)
	{
		$error = true;
		$show = 'invalidKey';
	} elseif ($result['status'] == true) {
		$error = false;
		$show = 'recoverForm';
		$securityUser = $result['userID'];
	}
}
if ($_SESSION['badCount'] >= 3)
{
	$show = 'speedLimit';
	$_SESSION['lockout'] = true;
	$_SESSION['lastTime'] = '' ? mktime() : $_SESSION['lastTime'];
}
?>

В else-блоке проверяется, установлена ли переменная $_GET[‘a’], и если это так, означает, что пользователь перешел по ссылке изменения пароля в письме. После того как мы выяснили, что пользователь перешел по этой ссылке, мы проверяем на валидность ключ, отправленный письмом, с помощью функции checkEmailKey(). Если ключ не найден или не верен, функция возвращает false и выводится сообщение о неверности ключа. Тем не менее, если ключ валиден, он возвращает массив, из которого мы можем получить пользовательский идентификатор (так мы узнаем, какому пользователю менять пароль).

ПРИМЕЧАНИЕ: если вы используете нешифруемые пароли, можете пропустить блок elseif. В этом блоке происходит отображение формы изменения пароля после того как пользователь перешел по ссылке из письма.

Во втором блоке if проверяется, ответил ли пользователь на секретный вопрос более 3 раз. Если это так, устанавливаем переменную блокировки в true и запоминаем время блокировки. Заметьте, если время блокировки уже установлено, мы используем это значение, а если нет, то генерируем новое значение.

Установка временного лимита необходима для безопасности. В основном, он будет служить для того, чтобы удержать людей от стараний угадать ответ на секретный вопрос. Также он предотвратит многократную отправку формы сетевыми роботами. Самой главной проблемой в этом методе является то, что пользователь может удалить куки и начать вводить ответ заново. Если вам необходимо обезопасить систему и в этом плане, то добавьте флаг «блокировки» к таблице пользователя и после 3 неудачных попыток установите его в true. Затем напишите фрагмент кода, который будет блокировать аккаунт, когда пользователь попытается получить к нему доступ.

Шаг 4. Файл методов

Теперь давайте создадим файл assets/php/functions.php со всеми функциями, которые мы ранее вызывали. Давайте рассмотрим их.

ПРИМЕЧАНИЕ: в примерах в случае шифруемых паролей используйте таблицу users_enc, а в случае нешифруемых — таблицу users, так что название таблицы в ваших методах будет зависеть от версии, которую вы используете.

<?php
define(PW_SALT,'(+3%_');

function checkUNEmail($uname,$email)
{
	global $mySQL;
	$error = array('status'=>false,'userID'=>0);
	if (isset($email) && trim($email) != '') {
		// адрес электронной почты был введен
		if ($SQL = $mySQL->prepare("SELECT `ID` FROM `users_enc` WHERE `Email` = ? LIMIT 1"))
		{
			$SQL->bind_param('s',trim($email));
			$SQL->execute();
			$SQL->store_result();
			$numRows = $SQL->num_rows();
			$SQL->bind_result($userID);
			$SQL->fetch();
			$SQL->close();
			if ($numRows >= 1) return array('status'=>true,'userID'=>$userID);
		} else { return $error; }
	} elseif (isset($uname) && trim($uname) != '') {
		// имя пользователя было введено
		if ($SQL = $mySQL->prepare("SELECT `ID` FROM `users_enc` WHERE Username = ? LIMIT 1"))
		{
			$SQL->bind_param('s',trim($uname));
			$SQL->execute();
			$SQL->store_result();
			$numRows = $SQL->num_rows();
			$SQL->bind_result($userID);
			$SQL->fetch();
			$SQL->close();
			if ($numRows >= 1) return array('status'=>true,'userID'=>$userID);
		} else { return $error; }
	} else {
		// ничего не было введено
		return $error;
	}
}

В самом начале мы определяем PW_SALT, где будет хранится соль, с помощью которой мы будем зашифровывать пароли. Первая функция по значениям логина и пароля проверяет через $_POST, существует ли такой пользователь в базе данных. В первую очередь нам необходимо сделать глобальной $mySQL, чтобы можно было получить доступ к базе данных. Мы также создаем динамический массив ошибок, который будет возвращаться в случае, если пользователь не найден. Затем мы проверяем, существует ли такой электронный адрес. Если он существует, создаем готовое mySQLi выражение. Большое преимущество в использовании готовых выражений заключается в безопасности, особенно когда дело касается ввода данных пользователем. В общем, процесс напоминает использование метода sprintf().

Заметьте, мы вызываем метод ->prepare() в качестве параметра SQL запроса и используем вопросительные знаки в местах, где должны быть наши переменные. Также заметьте, что мы не заключаем знаки вопроса ни в никакие кавычки (даже в случае строк). Это позволяет нам параметризировать выражение. Если выражение создано успешно, mySQLi::prepare() вернет истину. И если оно создано, нам необходимо привязать параметры к запросу с помощью mySQLi::bind_param(). В этой функции как минимум 2 аргумента. Первый — это строка символов, представляющая типы данных, которые должны быть привязаны. Остальные аргументы — это переменные, которые вы вставляете в каждый параметр. В нашем случае, это ‘s’ (для строки) и $email, так как переменная содержит адрес электронной почты. Заметьте, что порядок имеет значение, так что первый знак вопроса в запросе соответствует первой букве названия типа данных string и первой переменной.

Затем необходимо вызвать ->execute() и ->store_result(). Эти два метода выполняют подготовленные запросы и сохраняют их в памяти до освобождения. Затем мы сверяем количество возвращенных строк, чтобы удостоверится, что пользователь найден. ->bind_result() подобна ->bind_param(), но работает в другом направлении. Она позволяет получить возвращаемое значение из результата выполнения запроса и поместить его в локальную переменную. Перменные устанавливаются на основе их порядка в результате. Локальные переменные в действительности не создаются, пока мы не вызываем ->fetch(), после чего в переменную $userID запишется значение из базы данных. Затем с помощью ->close() мы освобождаем результаты запроса. В завершении, мы возвращаем массив с логическим значением и целочисленным значением идентификатора пользователя.

function getSecurityQuestion($userID)
{
	global $mySQL;
	$questions = array();
	$questions[0] = "Девичья фамилия матери?";
	$questions[1] = "Город, в котором родился?";
	$questions[2] = "Какой ваш любимый цвет?";
	$questions[3] = "Год окончания школы?";
	$questions[4] = "Имя первой любви?";
	$questions[5] = "Любимая модель машины?";
	if ($SQL = $mySQL->prepare("SELECT `secQ` FROM `users_enc` WHERE `ID` = ? LIMIT 1"))
	{
		$SQL->bind_param('i',$userID);
		$SQL->execute();
		$SQL->store_result();
		$SQL->bind_result($secQ);
		$SQL->fetch();
		$SQL->close();
		return $questions[$secQ];
	} else {
		return false;
	}
}

function checkSecAnswer($userID,$answer)
{
	global $mySQL;
	if ($SQL = $mySQL->prepare("SELECT `Username` FROM `users_enc` WHERE `ID` = ? AND LOWER(`secA`) = ? LIMIT 1"))
	{
		$answer = strtolower($answer);
		$SQL->bind_param('is',$userID,$answer);
		$SQL->execute();
		$SQL->store_result();
		$numRows = $SQL->num_rows();
		$SQL->close();
		if ($numRows >= 1) { return true; }
	} else {
		return false;
	}
}

getSecurityQuestion() принимает идентификатор пользователя и возвращает его секретный вопрос как строку. Делаем $mySQL глобальной снова. Затем мы создаем массив из 6 разных возможных секретных вопросов. Используя подобный вышеприведенному метод, мы узнаем, какой секретный вопрос выбрал пользователь, и возвращаем индекс этого вопроса в массиве.

checkSecAnswer() принимает идентификатор пользователя и ответ на вопрос и проверяет, верно ли ответил пользователь. Заметьте, для того, чтобы увеличить шансы совпадения введенного значения с записанным в базу данных, мы предварительно преобразовываем их к строчным буквам (это вам не обязательно). Это отличный пример подготовленного выражения с множеством параметров. Обратите внимание на порядок аргументов в методе bind_param(). Этот метод вернет истину, если в базе данных найдена запись, совпадающая с идентификатором пользователя и полученным ответом. В противном случае, вернется ложь.

function sendPasswordEmail($userID)
{
	global $mySQL;
	if ($SQL = $mySQL->prepare("SELECT `Username`,`Email`,`Password` FROM `users_enc` WHERE `ID` = ? LIMIT 1"))
	{
		$SQL->bind_param('i',$userID);
		$SQL->execute();
		$SQL->store_result();
		$SQL->bind_result($uname,$email,$pword);
		$SQL->fetch();
		$SQL->close();
		$expFormat = mktime(date("H"), date("i"), date("s"), date("m")  , date("d")+3, date("Y"));
		$expDate = date("Y-m-d H:i:s",$expFormat);
		$key = md5($uname . '_' . $email . rand(0,10000) .$expDate . PW_SALT);
		if ($SQL = $mySQL->prepare("INSERT INTO `recoveryemails_enc` (`UserID`,`Key`,`expDate`) VALUES (?,?,?)"))
		{
			$SQL->bind_param('iss',$userID,$key,$expDate);
			$SQL->execute();
			$SQL->close();
			$passwordLink = "<a href="?a=recover&email=" . $key . "&u=" . urlencode(base64_encode($userID)) . "">http://www.oursite.com/forgotPass.php?a=recover&email=" . $key . "&u=" . urlencode(base64_encode($userID)) . "</a>";
			$message = "Уважаемый(ая)$uname,rn";
			$message .= "Пройдите по ссылке, чтобы изменить пароль:rn";
			$message .= "-----------------------rn";
			$message .= "$passwordLinkrn";
			$message .= "-----------------------rn";
			$message .= "Ссылка будет действительно в течении 3х дней.rnrn";
			$message .= "Ничего не делайте, если вы не запрашивали восстановение пароля.rnrn";
			$message .= "Спасибо,rn";
			$message .= "-- Команда сайта ...";
			$headers .= "From: Our Site <webmaster@oursite.com> n";
			$headers .= "To-Sender: n";
			$headers .= "X-Mailer: PHPn"; // отправитель
			$headers .= "Reply-To: webmaster@oursite.comn"; // адрес отправителя
			$headers .= "Return-Path: webmaster@oursite.comn"; // для ошибок
			$headers .= "Content-Type: text/html; charset=iso-8859-1"; // тип данных
			$subject = "Восстановление пароля";
			@mail($email,$subject,$message,$headers);
			return str_replace("rn","<br/ >",$message);
		}
	}
}

Эта функция отправляет электронное письмо для изменения пароля. Начнем с создания SQL запроса, чтобы получить имя пользователя и его электронный адрес. После связывания параметров с результатами закрываем запрос. Для большей безопасности, мы оставим сгенерированную ссылку в рабочем состоянии в течении 3 дней. Для этого мы создаем новую дату, которая наступит через три дня. Затем, используя некоторые получаемые значения: дату, случайное число и соль, мы генерируем MD5 хэш, который и будет секретным кодом. Из-за того что дата и случайное число постоянно меняются, мы должны быть увернены в том, что секретный ключ уникален. Создаем SQL запрос, чтобы ввести его в базу данных. После выполнения запроса генерируем ссылку, которая будет отправляться в письме. Добавляем ‘a=recover’ и ключ, а также идентификатор пользователя, предварительно применив к нему base64_encode() и urlencode(), чтобы сделать его нечитабельным. Как только ссылка сгенерирована мы составляем остальную часть письма и отправляем его.

ПРИМЕЧАНИЕ: в случае нешифруемых паролей, измените письмо — выводите значение переменной $pword вместо ссылки на изменение пароля.

ПРИМЕЧАНИЕ: если вы разрабатываете сайт на локальном сервере, маловероятно, что smtp установлен, так что у вас не получится отправить письмо. Именно поэтому мы используем команду @mail(), чтобы избежать вывода сообщений об ошибке. По этой же причине эта функция возвращает строку с сообщением, так что его можно вывести на экран. А теперь последние 3 функции:

function checkEmailKey($key,$userID)
{
	global $mySQL;
	$curDate = date("Y-m-d H:i:s");
	if ($SQL = $mySQL->prepare("SELECT `UserID` FROM `recoveryemails_enc` WHERE `Key` = ? AND `UserID` = ? AND `expDate` >= ?"))
	{
		$SQL->bind_param('sis',$key,$userID,$curDate);
		$SQL->execute();
		$SQL->execute();
		$SQL->store_result();
		$numRows = $SQL->num_rows();
		$SQL->bind_result($userID);
		$SQL->fetch();
		$SQL->close();
		if ($numRows > 0 && $userID != '')
		{
			return array('status'=>true,'userID'=>$userID);
		}
	}
	return false;
}

function updateUserPassword($userID,$password,$key)
{
	global $mySQL;
	if (checkEmailKey($key,$userID) === false) return false;
	if ($SQL = $mySQL->prepare("UPDATE `users_enc` SET `Password` = ? WHERE `ID` = ?"))
	{
		$password = md5(trim($password) . PW_SALT);
		$SQL->bind_param('si',$password,$userID);
		$SQL->execute();
		$SQL->close();
		$SQL = $mySQL->prepare("DELETE FROM `recoveryemails_enc` WHERE `Key` = ?");
		$SQL->bind_param('s',$key);
		$SQL->execute();
	}
}

function getUserName($userID)
{
	global $mySQL;
	if ($SQL = $mySQL->prepare("SELECT `Username` FROM `users_enc` WHERE `ID` = ?"))
	{
		$SQL->bind_param('i',$userID);
		$SQL->execute();
		$SQL->store_result();
		$SQL->bind_result($uname);
		$SQL->fetch();
		$SQL->close();
	}
	return $uname;
}

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

Функция updateUserPassword() отвечает за изменение пароля в базе данных. Сперва мы сверяем ключ, отправленный письмом, с введенным пользователем ключом и информацию о ключе, чтобы удостовериться в безопасности. Генерируем новый пароль, соединив введенный пароль с ранее определенной солью, а затем применив к полученной строке метод md5(). Затем осуществляем обновление. После его заверешния удаляем запись кода восстановления из базы данных, чтобы исключить его повторное использование.

ПРИМЕЧАНИЕ: функция updateUserPassword() не требуется в случае нешифруемых паролей, так как мы не меняем пароли.

getUserName() — это просто вспомогательная функция, получающая имя пользователя по его идентификатору. В ней используются обычные SQL выражения, ничем не отличающиеся от других.

Шаг 5. Завершаем создание страницы восстановления пароля

После написания всех необходимых функций добавим кое-что еще в файл forgotPass.php. Вставьте этот код в блок (div) с идентификатором (id) «page»:

<?php switch($show) {
	case 'emailForm': ?>
	<h2>Восстановление пароля</h2>
    <p>Это форма для восстановления пароля. Введите ваш логин или email для того, чтобы начать.</p>
    <?php if ($error == true) { ?><span class="error">Введите логин или пароль чтобы продолжить.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="uname">Логин</label><div class="field"><input type="text" name="uname" id="uname" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label>- ИЛИ -</label></div>
        <div class="fieldGroup"><label for="email">Email</label><div class="field"><input type="text" name="email" id="email" value="" maxlength="255"></div></div>
        <input type="hidden" name="subStep" value="1" />
        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>
    <?php break; case 'securityForm': ?>
    <h2>Восстановление пароля</h2>
    <p>Ответьте на секретный вопрос:</p>
    <?php if ($error == true) { ?><span class="error">Для восстановления пароля вы должны правильно ответить на секретный вопрос.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label>Вопрос</label><div class="field"><?= getSecurityQuestion($securityUser); ?></div></div>
        <div class="fieldGroup"><label for="answer">Ответ</label><div class="field"><input type="text" name="answer" id="answer" value="" maxlength="255"></div></div>
        <input type="hidden" name="subStep" value="2" />
        <input type="hidden" name="userID" value="<?= $securityUser; ?>" />
        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>

	 <?php break; case 'userNotFound': ?>    <h2>Восстановление пароля</h2>    <p>Логин или email не был найден в базе.<br /><br /><a href="?">Нажмите тут</a> чтобы попробывать снова.</p>    <?php break; case 'successPage': ?>    <h2>Восстановление пароля</h2>    <p>На ваш email было отправлено письмо с инструкциями. <strong>(Mail не заработает пока вы локально не активируете работу smtp сервера.)</strong><br /><br /><a href="login.php">Вернуться</a> на главную. </p>    <p>Это сообщение, которое отправится на email:</p>    <div class="message"><?= $passwordMessage;?></div>    <?php break;

Этот фрагмент кода в действительности осуществляет отображение всех элементов интерфейса. Начнем с проверки переменной $show с помощью switch(). Как вы помните, переменная может принимать множество различных значений, так что нам необходимо проверить каждое из них. В первом случае, «emailForm», это имя пользователя или адрес его электронной почты. Вообще-то нам нужны два текстовых поля и одно скрытое поле ввода (hidden), так что мы будем знать, на какой стадии заполнения была отправлена форма. Блок if ($error == true) отобразит ошибку, если флаг $error установлен в true.

Второй случай — «securityForm». В нем будет отображатся секретный вопрос. У нас также есть сообщение об ошибке, которое отображается с помощью getSecurityQuestion(). У нас также есть поле для ввода ответа, а также стадия заполнения формы и идентификатор пользователя.

Сообщение для случая «userNotFound» — это просто текстовое сообщение, которое сообщает пользователю, что такая запись не была найдена.

«SuccessPage» отображается, когда ответ на секретный вопрос верен, и письмо было отправлено. Заметьте, что мы отобразили письмо, отправляемое пользователю, в этой подсказке. Вы не должны этого делать в реальных проектах, так как таким образом любой пользователь получит доступ к кодам безопасности, предназначенным только для зарегистрированных пользователей.

Далее следует фрагмент кода:

case 'recoverForm': ?>
    <h2>Восстановление пароля</h2>
    <p>И снова здрасти, <?= getUserName($securityUser=='' ? $_POST['userID'] : $securityUser); ?>.</p>
    <p>Введите ваш новый пароль.</p>
    <?php if ($error == true) { ?><span class="error">Новый пароль не может быть пустым.</span><?php } ?>
    <form action="<?= $_SERVER['PHP_SELF']; ?>" method="post">
        <div class="fieldGroup"><label for="pw0">Новый пароль</label><div class="field"><input type="password" class="input" name="pw0" id="pw0" value="" maxlength="20"></div></div>
        <div class="fieldGroup"><label for="pw1">Подтверждение пароля</label><div class="field"><input type="password" class="input" name="pw1" id="pw1" value="" maxlength="20"></div></div>
        <input type="hidden" name="subStep" value="3" />
        <input type="hidden" name="userID" value="<?= $securityUser=='' ? $_POST['userID'] : $securityUser; ?>" />
        <input type="hidden" name="key" value="<?= $_GET['email']=='' ? $_POST['key'] : $_GET['email']; ?>" />
        <div class="fieldGroup"><input type="submit" value="Submit" style="margin-left: 150px;" /></div>
        <div class="clear"></div>
    </form>
    <?php break; case 'invalidKey': ?>
    <h2>Неверный ключ</h2>
    <p>Вы ввели неверный ключ. Или срок восстановления (3 дня) уже истёк, или вы уже пользовались этим ключём.<br /><br /><a href="login.php">Вернуться</a> на главную страницу. </p>
    <?php break; case 'recoverSuccess': ?>
    <h2>Пароль изменён</h2>
    <p>Поздравляю! Вы успешно изменили свой пароль.</p><br /><br /><a href="login.php">Вернуться</a> на главную. </p>
    <?php break; case 'speedLimit': ?>
    <h2>Предупреждение</h2>
    <p>Вы много раз ответили неверно на секретный вопрос. Вы заблокированы на 15 минут.</p><br /><br /><a href="login.php">Вернуться</a> на главную. </p>
    <?php break; }
	ob_flush();
	$mySQL->close();
?>

«recoverForm» отображает форму для изменения пароля. Мы отображаем имя пользователя и сообщение об ошибке, если требуется. Далее следуют поля для ввода пароля, его подтверждения, стадии заполнения формы, идентификатора пользователя и ключа безопасности, полученного в письме. Для ключа и идентификатора пользователя используем специальную проверку в блоке if(), чтобы удостовериться, что мы получаем переменную из нужного места. Если строка запроса пуста, проверяем, есть ли значение у переменной post.

«invalidKey» означает, что введенный ключ не существует или срок его действия истек. Сообщение «speedLimit» отображается, если пользователь был заблокирован из-за многократного ввода неверных ответов. В завершение, вызываем ob_flush(), чтобы загрузить страницу в браузере, и $mySQL->close() для закрытия подключения к базе данных.

ПРИМЕЧАНИЕ: сообщения «recoverForm» и «invalidKey» не нужны в случае нешифруемых паролей.

Выводы

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

К тому же, мы рассмотрели mysqli в качестве взаимодействия с базой данных. Несмотря на то, что мы не углублялись в изучение mysqli, вы теперь знаете о ней немного больше, чем до этого.

Надеюсь, вы будете использовать техники, описанные выше, для добавления этой полезной функции в ваш следующий проект.

По поводу загрузки: в файлах для загрузки находятся версии для шифруемых и нешифруемых паролей в двух разных папках.

Здравствуйте.
Есть самописный сайт с регистрацией пользователей.
Вопрос заключается в следующем — как на сайте организовать функцию восстановления пароля пользователя через мыло которое указано при регистрации. Задумка есть но не будет ли она очередным велосипедом.

Я думаю сделать так.
На странице восстановить пароль выводится форма где пользователь указывает логин, мыло и возможно ответ на секретный вопрос (еще вариант указывать только логин). После отправки в базе идет поиск по логину, берется мыло этого пользователя, проверяется ответ на секретный вопрос если все ОК и мыло совпадает — генерится случайный хеш код который 1. Пишется в БД в строку юзера. 2. Формируется ссылка где в качестве get параметра передается этот хеш код, эта же ссылка передается на мыло пользователя.

При переходе по ссылке с письма с параметра get берется хеш проверяется есть ли он в таблице юзеров — если есть выводим форму изменения пароля с полями логин, новый пароль, ответ на секретный вопрос, если хеша нет выводим ошибку или перенаправляем на главную. После отправки поиск юзера в БД осуществляется по хешу — если все введенные данные совпадают меняем пароль а хеш из базы удаляем.
Оцените пожалуйста этот алгоритм. Буду признателен за ответ.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

Темы

  • Изменение пароля через профиль пользователя
  • Через ссылку восстановления
  • Через командную строку MySQL
  • Через phpMyAdmin
  • Через FTP
  • Через WP CLI
  • Использование сценария аварийного сброса пароля
  • Дополнительная информация

В WordPress есть несколько способов сбросить пароль. (Обычно самый простой способ сбросить его — воспользоваться ссылкой «Забыли пароль?» На главной странице входа в ваш блог или веб-сайт.) Однако бывают случаи (особенно, если ваша электронная почта работает некорректно), когда вам, возможно, придется предпринять другие шаги для сброса пароля.

Вот список различных способов сбросить пароль. Используемый вами метод зависит от типа доступа к вашему веб-сайту.

Изменение пароля через профиль пользователя

Изменить пароль в WordPress вы можете через настройки профиля пользователя. После того как вы выполнили вход в панель администрирования WordPress, зайдите в меню Пользователи → Ваш профиль и найдите раздел Новый пароль. Здесь вы можете задать новый пароль для текущего пользователя.

Если вы являетесь администратором сайта, то вы можете так же сменить пароль для другого пользователя, выбрав его в меню Пользователи → Все пользователи. Обратите внимание на шкалу надёжности, которая поможет вам выбрать более длинный и надёжный пароль.

Данный метод является самым простым и удобным, но к сожалению не применимым в тех случаях, когда вы не можете выполнить вход в панель управления WordPress. К счастью есть и другие варианты, не требующие входа.

Наверх ↑

Через ссылку восстановления

Если вы забыли пароль от вашего сайта на WordPress, то вы можете восстановить его по электронной почте. В форме входа (по адресу /wp-login.php) вы можете щёлкнуть ссылку «Забыли пароль» и ввести адрес электронной почты вашего пользователя или имя пользователя.

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

Если у вас нет доступа к электронной почте пользователя или если по какой-либо причине не работает отправка электронной почты с вашего сервера, то вам придётся воспользоваться другим методом.

Наверх ↑

Через командную строку MySQL

Если ваш хостинг провайдер не предоставляет пакет phpMyAdmin, то вы можете попытаться подключиться к вашей базе данных MySQL используя клиент MySQL через командную строку. Этот способ является более продвинутым и не рекомендуется новичкам.

Подключившись к серверу через SSH, выполните вход на сервер MySQL через командную строку, заменив значения username и password (а так же localhost, если вы подключаетесь к удалённой базе данных):

mysql -uusername -ppassword -hlocalhost

Если вам удалось подключиться, то так же как и в предыдущем способе, вам нужно найти вашу базу данных WordPress. Вы можете это сделать используя команды SHOW DATABASES:

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| wordpress          |
+--------------------+

Командой SHOW TABLES можно получить список всех таблиц определённой базы данных:

mysql> SHOW TABLES IN wordpress;
+------------------------------+
| Tables_in_wordpress          |
+------------------------------+
| wp_commentmeta               |
| wp_comments                  |
| wp_links                     |
| wp_options                   |
...

После того, как вы нашли интересующую вас базу данных, выберите её командой USE, и выведите список всех пользователей:

mysql> USE wordpress;
Database changed
mysql> SELECT user_login FROM wp_users;
+---------------+
| user_login    |
+---------------+
| admin         |
| user          |
...

Определив имя пользователя чей пароль вы хотите изменить, используйте команду UPDATE для смены пароля. Так же как и с phpMyAdmin, здесь необходимо воспользоваться функцией MD5 при вводе нового пароля:

mysql> UPDATE wp_users SET user_pass = MD5('newpassword') WHERE user_login = 'user';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

После выполнения данного запроса вы сможете выполнить вход в панель администрирования WordPress, используя ваш новый пароль.

При работе с запросами MySQL стоит быть предельно осторожным. Забыв например часть «WHERE…» в предыдущем запросе, вы измените пароли для всех пользователей и отменить это действие нельзя. Мы рекомендуем сделать резервную копию базы данных прежде чем начинать работу с консолью MySQL.

Наверх ↑

Через phpMyAdmin

Большинство хостинг-провайдеров предоставляют доступ к phpMyAdmin — это утилита для работы с базами данных MySQL, где WordPress хранит всю информацию о своих пользователях. Если вы не можете зайти в phpMyAdmin, советуем обратиться за помощью к вашему хостинг-провайдеру, или же попробовать другой способ смены пароля.

После того как вы выполнили вход в phpMyAdmin, найдите базу данных вашего сайта и выберите её в панели слева. Её легко распознать по наличию таблиц wp_posts, wp_postmeta, wp_comments, wp_commentmeta, wp_users, wp_usermeta и т.д. Учтите, что префикс может отличаться.

Здесь нас интересует таблица wp_users. После того как вы её откроете, вы увидите список всех пользователей вашего сайта. Выберите того пользователя, чей пароль вы хотите изменить и щёлкните кнопку «редактировать». Вам будет представлена форма редактирования пользователя.

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

После сохранения изменений вы сможете выполнить вход в панель администрирования WordPress используя ваш новый пароль. Учтите, что изменив пароль в phpMyAdmin, вы не увидите его в открытом виде в таблице wp_users, поскольку WordPress хранит все пароли в зашифрованом виде.

Наверх ↑

Через FTP

Когда другие методы не являются доступными, пароль в WordPress можно изменить с помощью простого PHP файла. Для данного способа вам понадобится доступ к FTP серверу, где хранится ваш сайт. Создайте новый PHP файл с произвольным именем (например password-recovery.php) и следующим содержанием:

<?php
add_action( 'init', 'my_password_recovery' );
function my_password_recovery() {
    $user = get_user_by( 'login', 'my-username' );
    wp_set_password( 'my-new-password', $user->ID );
}

Данный код находит в базе данных пользователя с заданным именем пользователя, и изменяет его пароль. Не забудьте заменить значения my-username и my-new-password на ваше имя пользователя и пароль.

После этого откройте ваш FTP клиент и подключитесь к серверу вашего сайта. В директории где установлен WordPress найдите папку wp-content и зайдите в неё. Найдите директорию mu-plugins (не путайте с директорией plugins). Если директория mu-plugins не существует — создайте её. Загрузите в директорию mu-plugins созданный вами PHP файл.

Конечный путь до файла должен выглядеть примерно так: wordpress/wp-content/mu-plugins/password-recovery.php

После того как вы загрузили ваш файл, вы сможете выполнить вход в административную панель WordPress используя пароль, который вы указали в вашем PHP файле.

И наконец, не забудьте снова зайти в вашу директорию mu-plugins и удалить созданный вами файл password-recovery.php. Если вы этого не сделаете, WordPress будет изменять пароль при каждом посещении вашего сайта, что существенно снизит скорость его работы.

Наверх ↑

Через WP CLI

WP CLI — это инструмент командной строки для управления вашей установкой WordPress.

  1. Перейдите в корневой каталог wordpress и введите
$ wp user list
  1. Затем обновите пользователя
$ wp user update 1 --user_pass=$UP3RstrongP4$w0rd

заменив «1» на идентификатор пользователя, которого вы хотите обновить.

Подробнее о wp cli

Наверх ↑

Использование сценария аварийного сброса пароля

Если другие перечисленные выше решения не работают, попробуйте сценарий аварийного сброса пароля. Обратите внимание, что это не плагин, это скрипт PHP.

Имейте ввиду, что:
  1. Сценарий экстренного сброса пароля требует, чтобы вы знали имя пользователя администратора.
  2. Он обновляет пароль администратора и отправляет электронное письмо на адрес электронной почты администратора.
  3. Даже если вы не получите письмо, пароль все равно будет изменен.
  4. Вам не нужно входить в систему, чтобы использовать его. (В конце концов, если бы вы могли войти в систему, сценарий вам не понадобился бы.)
  5. Поместите скрипт в корень вашей установки WordPress. Не загружайте его в каталог плагинов WordPress.
  6. По соображениям безопасности не забудьте удалить сценарий, когда закончите.
Инструкция по применению:
  1. Скопируйте аварийный сценарий из Скрипт аварийного пароля и поместите в файл с именем emergency.php в корне вашей установки WordPress (тот же каталог, который содержит wp-config.php).
  2. В вашем браузере откройте http://example.com/emergency.php.
  3. В соответствии с инструкциями введите имя пользователя администратора (обычно admin) и новый пароль, затем нажмите Обновить настройки. Появится сообщение об изменении пароля. Администратору блога будет отправлено письмо с измененным паролем.
  4. По завершении удалите emergency.php со своего сервера. Не оставляйте его на своем сервере, так как кто-то другой может использовать его для изменения вашего пароля.

Наверх ↑

Дополнительная информация

  • Вот еще один сценарий сброса пароля который можно использовать, не зная имени пользователя или электронной почты.

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

Создаем 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



Эта статья призвана познакомить разработчиков PHP с тем, как правильно реализовать функцию восстановления пароля в PHP. Все мы были когда-то начинающими разработчиками, когда-то мы считали md5 функцию безопасной.

Основная мотивация при написании этой статьи заключается в том, что порывшись в интернете я нашел море рекомендаций на этот счет, но большинство из них не имели ничего общего с безопасностью. В 2017 году 9 из 10 советов в выдаче гугла, да и по сей день довольно много в выдаче небезопасных советов. Хотелось бы немного внести свой вклад и дать людям безопасные варианты.

Теперь, когда с этим разобрались, давайте перейдем к делу.

Оригинал статьи

Содержание

  1. Как (не) стоит реализовать механизм восстановления пароля в PHP
  2. Не храните текстовые пароли в базе данных.
  3. Не используйте общедоступную информацию в качестве маркера восстановления пароля
  4. Не используйте последовательные идентификационные номера в качестве маркеров восстановления пароля.
  5. Не создавайте токены таким образом, который также может быть сгенерирован в автономном режиме кем-то со знанием системы
  6. Генерируйте токены, которые не зависят от пользовательских данных.
  7. Не создавайте свои токены на основе времени,они угадываются.
  8. Не используйте rand, mt_rand или lcg_value в качестве источника случайных чисел для чего-либо связанного с безопасностью.
  9. Используйте random_int или random_bytes для безопасных случайных чисел.
  10. Установите срок службы для ваших жетонов сброса, чем короче, тем лучше. 1 час, вероятно, разумное значение по умолчанию.
  11. Сбросьте жетоны сброса после использования.
  12. Резюмируем

Как (не) стоит реализовать механизм восстановления пароля в PHP

Ну все мы знаем этот функционал. Обычно это делается так: мы запрашиваем почту, которую указал пользователь при регистрации, затем отправляем на почту с ссылкой восстановления пароля. Обычно эта ссылка содержит в себе конкретную информацию, которая позволит приложению узнать, какой пользователь пришел, чтобы восстановить пароль. Затем пользователь указывает новый пароль и авторизуется.

Если вы вдруг задумались “почему бы им просто не отправить мне на почту пароль, который они и так знают”, то скорее всего вы не понимаете как правильно хранить пароли на сервере. Пароли, которые помещаются в базу всегда должны проходить процесс хеширования.

Не храните текстовые пароли в базе данных.

Ваш сайт хэширует ваши пароли перед сохранением их в БД? Хорошо, давайте двигаться дальше.

Возвращаясь к отправке по электронной почте пользователям ссылки, чтобы они могли сбросить свой пароль. Предположим, что url-адрес восстановления пароля вашего сайта:

https://your.site / password_recovery.php

Тривиальным решением (опять же, как видно из лучших результатов Google) может быть сделать что-то вроде:

https://your.site/password_recovery.php?user=john@gmail.com

Это не безопасно. Почему? Потому что если злоумышленник знает адрес электронной почты кого-то, он может изменить его пароль. Это наше второе “нет”.

Не используйте общедоступную информацию в качестве маркера восстановления пароля

Вы можете подумать: “Какая еще информация у меня есть от пользователя, которую я могу использовать? Может быть, user_id?”

https://your.site / password_recovery.php?user_id=13

Это тоже небезопасно. Почему? Хотя злоумышленник, скорее всего, не может знать, у какого пользователя он меняет пароль, он может заблокировать людей из их учетных записей. Кроме того, если ваш сайт имеет какую-то функцию администратора, то user_id=1, скорее всего, будет пользователем администратора, и теперь вы попали в мир боли.

Не используйте последовательные идентификационные номера в качестве маркеров восстановления пароля.

На этом этапе вы, вероятно, поняли, что не можете напрямую использовать что-либо из базы данных. Но в попытке обойти это вы думаете: “давайте использовать md5, который должен помешать злоумышленнику угадать пользователя правильно?”. Так что попробуйте что-нибудь вроде:

$token = md5($user["email"]);

https://your.site/password_recovery.php?token=$token

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

Это тоже небезопасно. Почему? Потому что если я могу угадать, как генерируется токен, например: посмотрев на мой токен (или вы опубликовали код в github, или, скажем, я выяснил, какие из топ-10 реализаций google вы копируете и вставляете), то я могу сгенерировать токен для всех. 

Следует проектировать системы, исходя из предположения, что враг сразу же получит полное знакомство с ними

Клод Шеннон

Не ставьте свою безопасность в зависимость от того, что ваш код является неизвестным злоумышленнику. Этого не будет.

Вот несколько вариантов из первой выдачи гугла:

$token = md5 (18247*2567 + $user ["id"]);
$salt = " некая строка !BIG#RANDOM@STRING1337 "
$token = md5 ($salt.$user ["email"])

Все три попадают в 4 пункт. Если я узнаю, как строится ваш хэш, я смогу создать токены восстановления для всех ваших пользователей. Даже если вы уверены, что 4 не относится к вам, не используйте их. Они уязвимы для других атак, которые выходят за рамки этой статьи, но не стесняйтесь нарушать их самостоятельно.

Кроме того, все они проваливают “атаку недовольного (бывшего) коллеги”, то есть: ваш коллега или вы сами можете создавать токены для любого пользователя, которого вы хотите, не взаимодействуя с системой. Это не очень хорошее свойство, чтобы иметь в такой системе.

Не создавайте токены таким образом, который также может быть сгенерирован в автономном режиме кем-то со знанием системы

– Но подождите!” вы можете подумать. “А что, если мы используем шифрование вместо хэширования? Я могу держать ключ вне контроля версий, и мы должны предотвратить эту проблему сверху, верно?”

Пока вы можете это сделать:

$token = encrypt($user ["email"],$some_key);

Это приносит больше проблем, чем решает.

  1. Вам нужно найти способ надежно обращаться с ключом.
  2. Если ключ будет скомпрометирован, и вы захотите его изменить, вы сломаете предыдущие токены.
  3. В зависимости от алгоритма и размера ключа Ключ может быть восстановлен, чему способствует тот факт, что открытый текст и алгоритм известны (см. Не 4).
  4. Если ключ восстановлен (либо с помощью bruteforce, либо из-за другой слабости где-то), то злоумышленник (или ваш коллега, см. Пункт 5 может генерировать токены сброса для любого пользователя в автономном режиме.

Не используйте шифрование, если вы можете избежать этого. Это вызывает больше проблем, чем решает.

На данный момент, вероятно, больше нет способов использовать данные, которые у вас уже есть для создания маркера сброса. Вместо этого вам придется генерировать его из каких-то других данных и хранить где-то, например, в новом столбце в таблице пользователей. Это действительно устраняет проблему создания действительных токенов в автономном режиме.

Генерируйте токены, которые не зависят от пользовательских данных.

С этого момента мы меняем модель атаки. До сих пор злоумышленник угадывал токен, связанный с конкретным пользователем. Это уже невозможно. Все, что может сделать злоумышленник, – это вызвать сброс пароля для пользователя и угадать, какой токен был сгенерирован.

“Так как же я буду генерировать этот токен?- ты сам себя спрашиваешь. Может быть, использовать что-то, что PHP уже дает нам, например uniqid:

php > echo uniqid();
593aceadf16aa

Это должен быть случайный, уникальный идентификатор, верно???

Изображение для поста

Да, но нет

Выходные данные uniqid генерируются исключительно из текущего времени сервера. Злоумышленник контролирует, когда он запрашивает изменение пароля, поэтому даже если разрешение, которое он использует, составляет до микросекунд, он, вероятно, может сузить диапазон до пары миллисекунд, что делает идентификатор угадываемым за пару тысяч попыток

Не создавайте свои токены на основе времени,они угадываются.

Примечание: хэширование угадываемого токена не добавляет никакой безопасности. Это похоже на то, как когда вы угадываете чей-то пароль, вам все равно, каков хэш его пароля, если вы можете просто догадаться, что пользователь ленив и его пароль буквально “пароль”.

В этот момент Вы, будучи умным парнем/девушкой, можете сказать: “зачем мне использовать uniqid, если я хочу что-то случайное. Я просто использую функции случайных чисел PHP!”

$token = rand (); / / значение между 0 и 2147483647.

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

И rand (), и mt_rand () уязвимы для такого рода атак. Менее известное значение lcg_value также есть. PHP 7 ввел random_bytes () и random_int (), которые возвращают случайные данные способом, безопасным для такого рода приложений, то есть они являются криптографически защищенными генераторами случайных чисел.

Не используйте rand, mt_rand или lcg_value в качестве источника случайных чисел для чего-либо связанного с безопасностью.

Используйте random_int или random_bytes для безопасных случайных чисел.

Так как же построить случайный и непредсказуемый токен?

Простой способ-это:

$length = 16; // отрегулируйте длину, чтобы соответствовать вашему новому уровню паранойи. 16, вероятно, является нормальным значением по умолчанию и такой же длиной, как md5 (если вы мигрируете из метода, который его использует)

$token = bin2hex(random_bytes($length)); // вывод bin2hex безопасен для url.

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

Теперь вы можете пойти дальше и реализовать остальную функциональность. Однако есть пара дополнительных вещей, которые вам нужно иметь в виду, когда вы это делаете.

Сброшенные токены не должны быть действительны вечно, поэтому вы должны добавить новый столбец рядом с токеном с датой создания и использовать его, чтобы проверить, следует ли его принять или нет. Кроме того, они должны быть одноразовыми токенами. Поэтому, как только пользователь сбросит свой пароль, удалите маркер.

Установите срок службы для ваших жетонов сброса, чем короче, тем лучше. 1 час, вероятно, разумное значение по умолчанию.

Сбросьте жетоны сброса после использования.

Резюмируем

Собрав все это вместе, ваш общий поток мыслей должен выглядеть примерно так:

  • пользователь запрашивает сброс пароля, предоставляя свою электронную почту
  • Найдите пользователя в базе данных, используя адрес электронной почты
  • надежно создайте токен и сохраните его в базе данных вместе со временем его создания. Напр.: $token = bin2hex(random_bytes(16));
  • отправьте электронное письмо со ссылкой на страницу Восстановления пароля и токеном в качестве параметра строки запроса
  • поиск пользователя в базе данных с помощью токена, если он найден и срок действия не истек, запросите у него новый пароль
  • сохраните новый пароль в базе данных
  • удалите используемый токен из базы данных.

Помни, чего не стоит делать:

  1. не храните незашифрованные пароли в базе данных.
  2. не используйте общедоступную информацию в качестве маркера восстановления пароля.
  3. не используйте последовательные идентификационные номера в качестве маркеров восстановления пароля.
  4. сделайте так, чтобы ваша безопасность не зависела от того, что ваш код является секретным.
  5. не генерировать токены таким образом, чтобы они также могли генерироваться в автономном режиме
  6. не используйте шифрование
  7. не генерируйте свои токены на основе времени
  8. не используйте rand, mt_rand или lcg_value в качестве источника случайных чисел для всего, что связано с безопасностью

Помни, как стоит делать:

  1. генерировать токены, которые не зависят от пользовательских данных, и хранить их в базе данных.
  2. используйте random_int или random_bytes для безопасных случайных чисел.
  3. установите срок службы для ваших токенов сброса.
  4. сбросьте токены сброса после использования.

Потерять доступы к сайту можно по разным причинам: забыли пароль или логин, взломали сайт и т.п. В любом случае, это не повод отчаиваться, так как в этой статье мы собрали для вас полное руководство по восстановлению доступов к сайту. Если для вас это вопрос срочный, то воспользуйтесь содержанием, указанным ниже, для перехода к интересующему пункту.

  • Восстановление доступа к админке сайта

    • Доступ к Wordpress

      • 1-ый способ. Восстановление пароля через почту
      • 2-ой способ. Есть FTP-доступ к сайту
      • 3-ий способ. Есть доступ к базе данных
      • 4-ый способ. «Последний шанс»
    • Доступ к Bitrix

      • 1-ый способ
      • 2-ой способ
      • 3-ий способ
    • Доступ к MODX

      • 1-ый способ
      • 2-ой способ
    • Доступ к OpenCart

      • 1-ый способ
      • 2-ой способ
      • 3-ий способ
      • 4-ый способ
  • Восстановление доступа к базе mysql

  • Восстановление доступа к хостингу

  • Восстановление доступа к регистратору домена

  • Заключение

Восстановление доступа к админке сайта

Наиболее популярный вид доступа к сайту, который может понадобиться восстановить – это доступ к административной панели сайта или к CMS. Ниже указаны способы для 5 распространённых CMS. Сразу предупрежу, что для восстановления понадобится наличие хотя бы доступа к хостингу сайта либо к почте админа.

Доступ к Wordpress

1-ый способ. Восстановление пароля через почту

Если ваш пароль перестал подходить по каким-либо причинам, то самый простой способ восстановить его – с помощью функции «Забыли пароль?».

  1. Нажмите на кнопку «Забыли пароль?».

    Восстановление пароля к WordPress

  2. Введите имя пользователя или email.

    Восстановление доступа к WordPress

  3. Откройте почту и следуйте указаниям в письме.

2-ой способ. Есть FTP-доступ к сайту

Необходимо найти файл functions.php в папке той темы, которая активна на сайте.

Необходимо открыть его через редактор кода (например, Notepad++) и добавить строку:

wp_set_password(’password’, 1);

Строку необходимо добавить в рамках php-кода:

Восстановление доступа к админке WordPress

После этого сохраните файл и закачайте его в ту же папку, где и скачивали. Файл нужно сохранять в кодировке UTF-8 без метки BOM.

Сохранение файла для восстановления доступа к WP

Далее заходим на сайт, на страницу авторизации в админ-панели. Логин указываем прежний (admin), а пароль вводим password.

Результат восстановления доступа к WordPress

Важно! Не забудьте удалить строку после авторизации в админ-панели, иначе пароль будет перезаписываться каждый раз при обращении к сайту. После этого поменяйте пароль на свой.

3-ий способ. Есть доступ к базе данных

Если по каким-то причинам предыдущий способ не подошёл, представляю вашему вниманию следующий вариант.

  1. Создаём файл с названием pass.php и со следующим содержимым:

    <?php
    $md5 = md5(«password«);
    print $md5;
    ?>

  2. Загружаем файл в корневую папку сайта.

  3. Переходим по ссылке https://адрес-сайта.ru/pass.php и копируем строку со страницы.

  4. Теперь откройте базу данных и найдите таблицу wp_users

  5. В открывшемся поле будет первая строка – чаще всего это данные админа.

  6. Выберите столбец user_pass и замените его содержимое на скопированное значение из пункта 3.

  7. Удалите данные из столбца user_activation_key, если там что-то заполнено.

  8. Авторизуйтесь в админ-панели сайта с помощью пароля password и смените пароль на свой.

4-ый способ. «Последний шанс»

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

  1. Необходимо загрузить в корневой каталог файл с названием reset-password.php и следующим содержимым:

    <?php

    require ’wp-load.php’;

    $user = get_user_by( ’login’, ’my-username’ );

    if ( $user ) {

    wp_set_password( ’my-new-password’, $user->ID );

    echo ’New password set.’;

    } else {

    echo ’Error: User not found.’;

    }

    ?>

  2. Вместо my-username введите ваш логин, а вместо my-new-password новый пароль.

  3. Откройте загруженный файл по адресу – https://адрес-сайта.ru/reset-password.php

  4. Если всё верно, то после этого вы сможете авторизоваться в админке. Если скрипт показывает «User not found», исправьте логин и повторите процедуру.

  5. Не забудьте удалить файл!

Доступ к Bitrix

1-ый способ

  1. Нажмите на кнопку «Забыли свой пароль?».

  2. Укажите логин пользователя или email.

    Восстановление доступа к админке Bitrix

  3. Откройте письмо и перейдите по ссылке.

  4. Укажите новый пароль.

2-ой способ

С помощью данного способа пароль восстанавливается для первого зарегистрированного пользователя, который из-за этого обладает администраторскими правами.

  1. Создайте php-файл с любым именем и сохраните в нём следующий скрипт:

    <?

    require($_SERVER[’DOCUMENT_ROOT’].«/bitrix/header.php»);

    echo $USER->Update(1,array(«PASSWORD«=>’Bitrix*123456′));

    echo $USER->LAST_ERROR;

    require($_SERVER[’DOCUMENT_ROOT’].«/bitrix/footer.php»);

    ?>

  2. Загрузите данный файл через FTP в корневой каталог www/имя сайта/.

  3. Откройте файл на сайте: https://адрес-сайта.ru/название-скрипта.php (после перехода будет назначен новый пароль: Bitrix*123456)

    Результат восстановления доступа к Bitrix

  4. Авторизуйтесь в админ-панели с новым паролем и установите свой.

    Восстановление доступа к Bitrix

Если закрыт доступ для неавторизованных пользователей, то сначала скорректируйте файл access.php в корне сайта, заменив:

$PERM[«/»][«*»]=»D»;

на

$PERM[«/»][«*»]=»R»;

3-ий способ

  1. Также сохраняем в php-файле новый скрипт:

    <? require($_SERVER[«DOCUMENT_ROOT«].«/bitrix/modules/main/include/prolog_before.php»);

    global $USER;

    $USER->Authorize(1);

    require($_SERVER[«DOCUMENT_ROOT«].«/bitrix/modules/main/include/epilog_after.php»);

    ?>

  2. Загрузите файл в корневой каталог www/имя сайта/.

  3. Откройте файл на сайте: https://адрес-сайта.ru/название-скрипта.php

  4. Зайдите в админ-панель – логин и пароль запрашиваться не будут.

  5. Смените пароль на свой и удалите файл скрипта.

Доступ к MODX

У обладателей данной CMS есть эксклюзивная «возможность» – быть заблокированным при вводе неправильных данных 3-5 раз подряд.

Восстановление доступа к админке MODX

Если вы точно помните пароль и неправильно его ввели, то можно разблокировать его следующим способом:

  1. Зайдите в базу данных.

  2. Найдите таблицу modx_user_attributes.

  3. Замените на 0 содержимое следующих полей:

    • blocked
    • blockeduntill
    • failedlogincount

    Снятие блокировки пользователя MODX через базу данных

  4. Авторизуйтесь в админ-панели под своими логином и паролем.

Если вы всё-таки забыли пароль, то ниже представлено 2 варианта восстановления.

1-ый способ

  1. Нажмите «Забыли свой пароль?».

    Восстановление пароля к MODX

  2. Укажите email учётной записи.

    Восстановление доступа к MODX

  3. Откройте почту – вам придёт письмо со ссылкой на сброс пароля.

  4. Перейдите по ссылке и укажите свой пароль.

2-ой способ

Если у вас нет доступа к почте, то можно восстановить доступ следующим способом:

  1. Зайдите в базу данных сайта.

  2. Найдите таблицу modx_user_attributes.

  3. Замените почту на ту, к которой есть доступ.

    Восстановление почты админа для MODX

  4. Выполните процедуру из 1-го способа.

Доступ к OpenCart

1-ый способ

  1. Нажмите кнопку «Забыли пароль?».

    Восстановление пароля к админке Opencart

  2. Введите email администратора.

    Восстановление доступа к Opencart через почту

  3. Перейдите по ссылке из письма.

  4. Введите новый пароль.

2-ой способ

Если забыли и пароль, и email, то восстановим через базу данных.

  1. Создаём файл с названием pass.php и со следующим содержимым:

    <?php
    $md5 = md5(«password«);
    print $md5;
    ?>

  2. Загружаем файл в корневую папку сайта.

  3. Переходим по ссылке https://адрес-сайта.ru/pass.php и копируем строку со страницы.

  4. Откройте базу данных через phpMyAdmin или через интерфейс, который вы используете.

  5. Найдите таблицу с названием «префикс вашей базы данных + _user» и откройте её.

  6. Замените значение поля password на скопированное значение из пункта 3 (у вас может получиться набор символов, отличный от приведенного на скриншоте):

    Восстановление доступа к Opencart через базу данных

  7. Зайдите на страницу авторизации и введите ваш логин и пароль password.

  8. Смените пароль на свой.

3-ий способ

Не помните ни пароль, ни email, ни доступа к базе данных через панель хостинга? Данный вариант поможет восстановить доступ к админ-панели.

  1. Откройте через FTP файл config.php и найдите информацию о базе данных.

    Информация о базе данных для восстановления доступа к Opencart

  2. Подключитесь к базе данных через MySQL-менеджер.

  3. Повторите процедуру из 2-го способа.

4-ый способ

  1. Создайте в корне сайта файл user.php со следующим содержимым:

    <?php

    error_reporting(-1);

    header(’Content-Type: text/html; charset=utf-8′);

    include(’config.php’);

    $db = mysqli_connect(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);

    $user = ’Login’; // Логин пользователя

    $password_user = ’Password’; // Пароль пользователя

    $password = md5($password_user);

    $mail = ’[email protected]’; // Email пользователя

    $query_content = «INSERT INTO `» . DB_PREFIX . «user` (`user_group_id`, `username`, `password`, `salt`, `firstname`, `lastname`, `email`, `image`, `code`, `ip`, `status`, `date_added`) VALUES

    (1, ’$user’, ’$password’, ’’, ’$user’, ’’, ’$mail’, ’’, ’’, ’127.0.0.1′, 1, ’2000-01-01 00:00:00’);»;

    $result_content = mysqli_query($db, $query_content);

    if (!$result_content) {

    echo «<p>Пользователь <strong style=»color:red;»>$user</strong> не создан!</p>»;

    } else {

    echo «<p>Пользователь <strong style=»color:green;»>$user</strong> c паролем <strong style=»color:green;»>$password_user</strong> успешно создан!</p>»;

    }

    ?>

    Восстановление доступа к админке Opencart

  2. Перейдите по адресу https://адрес-сайта.ru/user.php – вы увидите уведомление об успешном создании пользователя и доступы для авторизации.

    Результат восстановления доступа к Opencart

  3. Авторизуйтесь по указанным доступам и смените пароль.

    Как восстановить доступ к Opencart

Восстановление доступа к базе mysql

  1. Необходимо найти конфигурационный файл:

    CMS

    Путь к файлу и его имя

    Для WordPress

    /wp-config.php

    Для Bitrix

    /bitrix/php_interface/dbconn.php

    Для MODX

    /manager/includes/config.inc.php

    Для Opencart

    /config.php

  2. Откройте данный файл и найдите строки с названием базы данных, логином и паролем.

  3. Откройте интерфейс phpMyAdmin, используя полученные логин и пароль.

  4. Готово!

Восстановление доступа к хостингу

Самый тяжёлый случай, так как восстановить доступ к хостингу можно только одним способом. Если у вас сохранились платёжные документы, то обратиесь в поддержку хостинга и предоставьте им все подтверждающие документы, после чего они помогут вам.

Восстановление доступа к регистратору домена

Принцип тот же самый, что и с доступами к хостингу: пишем запрос в поддержку хостинга и предоставляем им документы, подтверждающие личность/организацию. Возможно, понадобятся платёжные документы.

Заключение

В данной инструкции я постарался указать способы решения наиболее распространённых проблем. Если для вашего случая не подходит ни один из способов – напишите нам в комментарии или отправьте запрос на странице контактов.

А если вы по каким-либо причинам не можете восстановить доступы к сайту самостоятельно, то наши специалисты помогут вам – просто напишите или позвоните нам.

#1

Tony_Chg

    Новый участник

  • Members
  • Pip

  • 2 сообщений
  • ФИО:Tony

Отправлено 11 мая 2021 — 03:43

Здравствуйте! Для теста имеется веб форма восстановления пароля. Нашёл, что при попытке восстановления, форма отправляет письмо на не зарегистрированный/не существующий email. Подскажите пожалуйста, что ещё следует проверить в этом форме?

  • 0

  • Наверх


#2

Vasiliy

Vasiliy

  • ФИО:Касимов Василий
  • Город:Москва

Отправлено 11 мая 2021 — 07:49

Попробуйте вот здесь поискать еще идеи — http://wiki.software…_Алексея_Лупана

  • 0

  • Наверх


#3

Tony_Chg

Tony_Chg

    Новый участник

  • Members
  • Pip

  • 2 сообщений
  • ФИО:Tony

Отправлено 12 мая 2021 — 08:23

Большое спасибо

  • 0

  • Наверх


#4

Snap

Snap

  • ФИО:Роман
  • Город:Москва

Отправлено 20 мая 2021 — 12:07

Здравствуйте! Для теста имеется веб форма восстановления пароля. Нашёл, что при попытке восстановления, форма отправляет письмо на не зарегистрированный/не существующий email. Подскажите пожалуйста, что ещё следует проверить в этом форме?

Я знаю сервисы, которые отправляют ссылку для получения пароля на незарегистрированный email (не существующий email система проверить вряд ли может). Тут нужно сопоставлять с ТЗ.

  • 0

  • Наверх


Понравилась статья? Поделить с друзьями:
  • Сценарий волшебные конфеты старшая
  • Сценарий вручения короны юбиляру
  • Сценарий волшебные искры нового года
  • Сценарий вручения ключей от новых квартир
  • Сценарий волшебные валенки деда мороза