Один пользователь, пароль в файле

Создадим самую простейшую конструкцию - файл (одну страницу сайта), защищенный паролем.

При попытке обратится к нему, он будет выдавать поле ввода пароля.

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

В случае успешного ввода пароля - форма ввода больше не должна показываться. Пароль будем хранить прямо в файле. Файл назовем index.php.

Код файла index.php

<?php
	$password = '12345'; //зададим наш пароль

	//Если форма отправлена и пароль из формы совпадает с паролем в файле...
	if ( !empty( $_REQUEST['password'] ) and $_REQUEST['password'] == $password ) {
		echo 'Доступ открыт!'; //здесь напишем код, доступ к которому закрыт паролем
	} else
	/*
		В случае, если форма еще не была отправлена 
		либо пароль неверен - покажем форму авторизации:
	*/
	{
?>
		<form action='index.php' method='GET'>
			<input name='password'>
			<input type='submit' value='Отправить'>
		</form>
<?php
	}
?>

Этот скрипт далеко не совершенен. Но не расстраивайтесь, сейчас мы его поправим!

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

Сделаем это:

Код файла index.php

<?php
	$password = '12345'; //зададим наш пароль

	//Если форма отправлена и пароль из формы совпадает с паролем в файле...
	if ( !empty( $_REQUEST['password'] ) and $_REQUEST['password'] == $password ) {
		echo 'Доступ открыт!'; //здесь напишем код, доступ к которому закрыт паролем
	} else {
		/*
			Если форма была отправлена, НО пароль неправильный...

			Обратите внимание на то, что этот код НЕ сработает
			ни в случае, когда форма еще не была отправлена,
			ни в случае, когда введен правильный пароль.
		*/
			if ( !empty($_REQUEST['password']) and $_REQUEST['password'] != $password ) {
				echo 'Неправильный пароль!<br>'; //выведем сообщение об ошибке
			}

		/*
			В случае, если форма еще не была отправлена 
			либо пароль неверен - покажем форму авторизации:
		*/
?>
		<form action='index.php' method='GET'>
			<input name='password'>
			<input type='submit' value='Отправить'>
		</form>
<?php
	}
?>

Теперь наш скрипт стал немного удобнее!

И следующей нашей задачей является защита пароля от злоумышленника.

Защита пароля от злоумышленника

Замените текст на звездочки

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

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

Чтобы добиться такого эффекта, нужно для инпута с паролем указать атрибут type='password':

	<form action='index.php' method='GET'>
		<input name='password' type='password'>
		<input type='submit' value='Отправить'>
	</form>

И теперь, даже если кто-то стоит у вас за спиной, он не сможет прочитать пароль с экрана.

Не используйте method='GET'

Обратите теперь свое внимание на строку <form action='index.php' method='GET'> - я специально использую метод отправки GET, чтобы показать вам, что так не стоит делать.

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

Поэтому для всех форм с паролями используется только метод POST.

Исправленная форма будет иметь следующий вид:

<form action='index.php' method='POST'>
	<input name='password' type='password'>
	<input type='submit' value='Отправить'>
</form>

Хешируем пароль. Функция md5

Что будет в случае, если злоумышленник получит доступ к нашему файлу? Он сможет посмотреть там наш пароль и впоследствии успешно авторизоваться.

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

Хеш - это набор символов, соответствующий нашей строке, причем для одной строки хеш всегда будет одним и тем же.

Самая популярная функция такого рода в PHP - это md5().

Пример хеша пароля md5('12345'): 827ccb0eea8a706c4c34a16891f84e7b.

По хешу никак нельзя восстановить пароль.

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

Потренируйтесь сами: найдите md5 от различных строк: '1234567890', 'пароль', 'юзер'.

Как использовать хеш

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

Если хеши совпадают - значит пароли одинаковы, даем доступ.

Смотрите пример:

<?php
	$password = '827ccb0eea8a706c4c34a16891f84e7b '; //md5 от '12345'

	//Если форма отправлена и md5 пароля из формы совпадает с паролем в файле...
	if ( !empty( $_REQUEST['password'] ) and md5($_REQUEST['password']) == $password ) {
		echo 'Доступ открыт!'; //здесь напишем код, доступ к которому закрыт паролем
	} else {
		//Если форма была отправлена, НО пароль неправильный...
		if ( !empty($_REQUEST['password']) and md5($_REQUEST['password']) != $password ) {
			echo 'Неправильный пароль!<br>'; //выведем сообщение об ошибке
		}

		/*
			В случае, если форма еще не была отправлена 
			либо пароль неверен - покажем форму авторизации:
		*/
?>
		<form action='index.php' method='POST'>
			<input name='password' type='password'>
			<input type='submit' value='Отправить'>
		</form>
<?php
	}
?>

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

Запускаем сессию

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

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

Впрочем, даже если мы просто обновим страницу - она снова выдаст нам пароль.

Для решения этой проблемы следует использовать сессии PHP.

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

Первый файл auth.php будет отвечать за авторизацию. Его обязанности:

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

Этот код на уже знаком и будет выглядеть примерно так:

Код для файла auth.php

<?php
	$password = '827ccb0eea8a706c4c34a16891f84e7b '; //md5 от '12345'

	//Если форма отправлена и md5 пароля из формы совпадает с паролем в файле...
	if ( !empty( $_REQUEST['password'] ) and md5($_REQUEST['password']) == $password ) {
		session_start(); //стартуем сессию

		//Запишем в сессию информацию о том, что мы авторизовались:
		$_SESSION['auth'] = true; 
	} else {
		//Если форма была отправлена, НО пароль неправильный...
		if ( !empty($_REQUEST['password']) and md5($_REQUEST['password']) != $password ) {
			echo 'Неправильный пароль!<br>'; //выведем сообщение об ошибке
		}

		/*
			В случае, если форма еще не была отправлена 
			либо пароль неверен - покажем форму авторизации:
		*/
?>
		<form action='index.php' method='POST'>
			<input name='password' type='password'>
			<input type='submit' value='Отправить'>
		</form>
<?php
 	}
?>

Все остальные страницы сайта должны проверять авторизован ли пользователь и изменять свое поведение в зависимости от ответа.

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

Вот пример кода такой страницы:

Код для остальных файлов, к которым нужно закрыть доступ

<?php
	session_start(); //стартуем сессию

	//Если переменная auth из сессии не пуста и равна true, то дадим доступ:
	if (!empty($_SESSION['auth']) and $_SESSION['auth']) {
		/*
			Этот участок кода выполнится для пользователя, 
			прошедшего авторизацию.
		*/
	}
	else echo 'Доступ запрещен!';
?>

Можно закрыть доступ не для всей страницы, а только для ее части.

Например, мы НЕавторизованному пользователю мы хотим показать ссылку на авторизацию, а авторизованному - ссылку на личный кабинет:

<?php
	//Сессию мы стартовали где-то выше, поэтому тут ее не стартуем.

	//Если переменная auth из сессии не пуста и равна true, то дадим доступ:
	if (!empty($_SESSION['auth']) and $_SESSION['auth']) {
		/*
			Этот участок кода выполнится для пользователя, 
			прошедшего авторизацию.

			Покажем ссылку на личный кабинет:
		*/
		echo '<a href="cabinet.php"> Личный кабинет </a>';
	}
	else 
	{ 
		/*
			Этот участок кода выполнится для пользователя, 
			НЕ прошедшего авторизацию.

			Покажем ссылку на авторизацию:
		*/
		echo '<a href="auth.php"> Авторизация </a>';
	}
?>

Логаут

Авторизованный пользователь должен иметь возможность перестать им быть.

Для этого следует сделать ссылку 'выйти' ('logout' по-английски).

При переходе по этой ссылке должна выполниться функция session_destroy(), которая уничтожит все сессии ДАННОГО пользователя, тем самым закончив его авторизацию.

И он станет уже неавторизованным пользователем.

Создадим файл logout.php, при переходе на который происходит логаут:

Код для файла logout.php

<?php
	session_start(); //стартуем сессию, иначе будет ошибка при попытке разрушить
	session_destroy(); //разрушаем сессию для пользователя
?>