|
| |||||||||||||||||
PHP и WEB для новичков (часть 14):Автор: Владислав Демьянишин
Авторизация и безопасность![]() Ограничение доступа к конкретным скриптам можно осуществить несколькими способами:
Средства ApacheПервый способ - без применения PHP, исключительно средствами Apache. Все скрипты, к которым следует ограничить доступ, помещаются в одну папку. В файл .htaccess, расположенный в этой папке, дописываем ограничение доступа, например, так:
AuthUserFile /home/multimedia/www/admin/.htpasswd
AuthGroupFile /dev/null
AuthName "Enter password"
AuthType Basic
<Limit GET POST>
require valid-user
</Limit>
Такие настройки означают, что при доступе (методами GET или POST) к какому-либо файлу в папке с таким .htaccess будет затребована авторизация. Имена и пароли пользователей для авторизации должны находиться в файле /home/multimedia/www/admin/.htpasswd.
Такой файл можно создать при помощи утилиты htpasswd.exe (размер 30 Кб), входящей в комплект поставки Денвера и находящейся в папке z:usrlocalapachebin или можно скачать на сайте нашего журнала в разделе Скачать полезные программы. Если ее запустить, например, так:
htpasswd.exe -cb .htpasswd admin admin
то она создаст файл .htpasswd, который будет содержать имя admin и пароль admin для доступа к папке. Давайте рассмотрим на практике. Создадим в папке multimedia папку admin. В ней создадим файл .htaccess с текстом, указанным выше.
Замечу, что совпадение названия логина admin, пароля admin и папки admin совершенно случайны и выбраны лишь для примера. Если хотите, можете их назвать по-своему.
При помощи htpasswd.exe создадим файл паролей с именем admin и паролем admin. Он будет примерно таким:
admin:$apr1$.25.....$UOiknU8j7IppBKehQ.wS1.
Строка после слова admin - это зашифрованный пароль и в этом файле он каждый раз разный - это нормально. Поместим файл .htpasswd в папку admin. Составим тестовый скрипт index.html там же, а содержаться в нем будет следующее:
<html>
<head>
<title>доступ разрешен</title>
</head>
<body>
<h1>доступ разрешен</h1>
</body>
</html>
Теперь попробуем загрузить что-нибудь из этой папки, набрав в браузере адрес multimedia/admin. Появится окошко с требованием ввести пароль (рис. 1).
![]() Рис. 1
Если будем пытаться вводить неверный логин и пароль, то окошко с требованием авторизоваться будет возникать снова. Если нажмем на кнопку "Отмена", то увидим сообщение об отказе в доступе (рис. 2).
![]() Рис. 2
И только указав требуемые логин и пароль (admin:admin), мы получим доступ к папке. Такой доступ будет сохраняться до тех пор, пока не закроем окно (все окна) браузера.
Средства PHPТакой способ удобен, когда нам необходимо ограничить доступ именно к какой-то папке, например, к папке с файлами для скачки. Если же нам необходим более гибкий контроль доступа, можно воспользоваться авторизацией при помощи средств PHP. Удалим папку admin и напишем в папке multimedia тестовый скрипт test.php:
<?
$login = @$_SERVER['PHP_AUTH_USER'];
$password = @$_SERVER['PHP_AUTH_PW'];
if( $login != "admin" ¦¦ $password != "admin" ) {
header('WWW-Authenticate: Basic realm="Enter password"');
header('HTTP/1.0 401 Unauthorized');
echo 'Доступ к этой странице невозможен без авторизации.';
exit;
}
else echo "<p>Привет, $login</p>";
?>
Этот пример делает то же самое. Что и авторизация при помощи .htaccess, но, во-первых, этот способ дает больше возможностей для проверки пароля (например, с сохранением паролей в базе данных), а во-вторых, предоставляет возможность разграничения доступа к отдельным скриптам, а не на всю папку в целом.
Обратите внимание на то, что такую конструкцию следует указывать в скрипте в самом его начале, чтобы до вызова функции header() не было ни единого вывода в браузер, например, echo.
Такая авторизация (средствами HTTP-заголовка 401) называется базовой HTTP-авторизацией.
Авторизация сессиейТретий способ - авторизовать пользователя при помощи сессий. Как работают сессии, вы уже могли узнать из предыдущих статей, а как это применяют для авторизации, посмотрим на примере для нашего сайта. Сначала создадим в базе данных таблицу для хранения логинов и паролей администраторов, например, так:
$link = @mysql_connect("localhost", "multimedia_user", "12345");
if(!$link){
echo "невозможно подключиться к серверу: ".mysql_error();
exit;
}
if(!mysql_select_db("multimedia")){
echo "невозможно подключиться к БД: ".mysql_error();
exit;
}
mysql_query("CREATE TABLE users (".
"`u_id` INT NOT NULL auto_increment,".
"`u_name` VARCHAR( 128 ) character set utf8 collate utf8_bin NOT NULL ,".
"`u_mail` VARCHAR( 128 ) NOT NULL ,".
"`u_login` VARCHAR( 128 ) NOT NULL ,".
"`u_password` VARCHAR( 32 ) NOT NULL ,".
"`u_area` VARCHAR( 128 ) NOT NULL ,".
"`u_privilege` VARCHAR( 128 ) NOT NULL ,".
"PRIMARY KEY (`u_id`,`u_login`),".
"UNIQUE KEY `u_id` (`u_id`))");
$err = mysql_error();
If($err<>"") echo "<BR>Ошибка: ".$err."<BR>";
mysql_query("INSERT INTO users ( u_login, u_password ) VALUES('admin', 'admin' )");
Поясню код, хотя все и так уже должно быть понятно. Процедура подключения к БД уже должна быть вам известна из предыдущих статей. Команда mysql_query создает таблицу с именем "users". Поле u_id, идентифицирующее пользователя в БД для управления списком пользователей, имеет опцию автоинкремента. Т.е. это поле нет необходимости инициализировать каким-либо значением при добавлении нового пользователя, поскольку уникальное сквозное значение будет назначено ему сервером БД автоматически.
Поле u_name содержит ФИО пользователя. Это для ясности. Поле u_mail для функции напоминания или восстановления пароля и служебных уведомлений. Поля u_area и u_privilege можно использовать для хранения идентификаторов доступных пользователю областей сайта и его привилегий в доступе (чтение, добавление, изменение, удаление и др.).
Далее идут две SQL-команды назначения первичных ключей для оптимизации поиска (поиск зачастую ведется именно по логину при авторизации, а по ID при администрировании списка пользователей) и назначения уникального ключа.
И вторая команда mysql_query добавляет запись пользователя (admin:admin) в таблицу БД. Разумеется, сейчас нас интересуют только поля логина и пароля.
Хранить пароли в натуральном виде, т.е. в том, в котором они вводятся пользователем, не рекомендуется из соображений безопасности. Например, БД с паролями к банковским счетам могут выкрасть. Но если пароли в ней зашифрованы, то ими не смогут воспользоваться. Поэтому теперь следует рассказать о шифровании паролей.
Обычно в системах, которые имеют право называться безопасными, пароли шифруют. Это означает, что пароль пользователя нигде не хранится в открытом виде. Т.е. в том виде, в котором пользователь его вводит при регистрации или проверке пароля. Пароли шифруют.
Не вдаваясь в подробности теории шифрования, покажу лишь практический пример. В PHP для шифрования применяют функцию crypt(). Напишем небольшой скрипт (например, add_crypt_pass.php) для шифрования пароля:
$pass = crypt("admin");
mysql_query("INSERT INTO users ( u_login, u_password ) VALUES('admin', '".$pass."' )");
Код подключения к БД я не показываю, он есть выше. Теперь в БД будем иметь примерно такую строку вместо пароля "$1$t.1.yN/.$lTzXclWSJthw8EE.jptee1". Это значит, что содержимое поля u_password зашифровано. В вашем случае эта строка будет иной. На самом деле значение даже одного и того же пароля при каждом шифровании будет разным.
ВАЖНО! Смысл такого шифрования в том, что по зашифрованному паролю невозможно восстановить пароль, но можно проверить его соответствие.
Так, в данном случае, невозможно расшифровать строку "$1$t.1.yN/.$lTzXclWSJthw8EE.jptee1" таким образом, чтобы получить оригинальную строку "admin". Тем ни менее, если необходимо получить ответ на вопрос "а ни строка ли admin была зашифрована", то совершенно четко можно получить ответ "Да" или "Нет".
На первый взгляд это может казаться странным, но так оно и есть. Поэтому, даже если злодей и заполучит доступ к БД с паролями, он не сможет узнать их и воспользоваться ими.
Как же проверить правильность введенного пользователем пароля в случае его шифрования? На самом деле функция crypt() может принимать два аргумента: первый - строка, подлежащая шифрованию, а второй - ключ.
Если введенный пользователем текст зашифровать ключом, в роли которого подставить зашифрованный пароль из БД, то получим тот же самый ключ. Так можно проверить правильность пароля. Давайте рассмотрим поясняющий пример:
$pass1 = "admin"; // нешифрованный пароль 1
$pass2 = "12345"; // нешифрованный пароль 2
// зашифрованный пароль admin
$crypted_pass = '$1$t.1.yN/.$lTzXclWSJthw8EE.jptee1';
// проверяем пароль 1
if(crypt($pass1, $crypted_pass) == $crypted_pass)
echo "пароль $pass1 Ok<br>";
else echo "пароль $pass1 Error<br>";
// проверяем пароль 2
if(crypt($pass2, $crypted_pass) == $crypted_pass)
echo "пароль $pass2 Ok<br>";
else echo "пароль $pass2 Error<br>";
Скрипт выдаст ответ:
пароль admin Ok
пароль 12345 Error
Перейдем к практическому применению. На нашем сайте http://multimedia сделаем возможность входа пользователя с проверкой пароля. Составим скрипт login.php и сохраним его в папку admin.
<?
session_start();
// Соединяемся с БД
$link = @mysql_connect("localhost", "multimedia_user", "12345");
…
if(!@$_SESSION["is_authorized"])
if(isset($_POST["login"]) && isset($_POST["password"])){
$login = $_POST["login"];
$password = $_POST["password"];
// запрашиваем шифрованный пароль по введенному логину
$res = mysql_query( "SELECT u_password FROM users WHERE u_login='$login'" );
$err = mysql_error();
If($err=="") {
if(mysql_num_rows($res)>0) {
$crypted_pass = mysql_result($res, 0, "u_password" );
if(crypt($password, $crypted_pass) == $crypted_pass){
// пароль правильный
$_SESSION["is_authorized"] = true;
$_SESSION["login"] = $login;
}
}
}
}
if(@$_SESSION["is_authorized"]){
// форма выхода
?>
<H1>Привет, <? echo $_SESSION["login"] ?></H1>
<div><a href="/logout.php">выход</a></div>
<?
}
else{ // форма входа
?>
<form method="post">
логiн:<input type="text" name="login" /><br />
пароль:<input type="password" name="password" /><br />
<input type="submit" value="вход" />
</form>
<?
}
?>
Этот скрипт устанавливает значения переменных сессии is_authorized (true или false) и login в зависимости от того, прошел логин проверку или нет. Сначала пользователь видит форму входа (рис. 3), требующую ввести логин и пароль.
![]() Рис. 3
После указания логина, пароля и нажатия кнопки "ВХОД" произойдет проверка, в результате которой при успехе пользователь увидит страницу с приветствием (рис. 4). Данный код можно вставить в каждый скрипт, в котором должна появиться форма входа и проверка пользователя.
![]() Рис. 4
Также создадим скрипт logout.php для выхода и поместим его вне папки admin. Все, что ему следует сделать - это сбросить значение переменной сессии is_authorized в false и переадресовать на скрипт, который его вызвал (реферер). Поэтому скрипт этот очень прост:
<?
session_start();
$_SESSION["is_authorized"] = false;
$_SESSION["login"] = "";
header("Location: ".$_SERVER["HTTP_REFERER"]);
?>
После выполнения этого скрипта можно делать проверку, правильный ли пароль указал пользователь (в этом случае $_SESSION["is_authorized"] == true) и соответственно давать или не давать ему доступ к административным функциям. Предлагаю сделать скрипты для добавления исполнителей, альбомов и песен самим. Это и будет вашим домашним заданием.
Аналогичным способом шифрования можно при помощи скрипта формировать файл .htpasswd самому. При этом как на одного пользователя, так и на нескольких сразу, просто в каждой новой строке очередной пользователь в виде login:crypted_pass. Если хранить пароли в массиве $Logins, то сохранить все пары login:password можно при помощи следующего кода:
$text = $Logins[0]["login"].":".crypt($Logins[0]["pass"]);
for ($j=1;$j<count($Logins);$j++)
$text .= "n".$Logins[$j]["login"].":".crypt($Logins[$j]["pass"]);
$f_out = fopen(".htpasswd", "w");
fwrite($f_out, $text);
fclose($f_out);
И запомните, что вовсе не обязательно таблицу пользователей называть "users". Можно назвать как-то по-другому, например, "members". Главное, чтобы хакер, прощупавший дыры в вашей защите не смог быстро обнаружить список паролей.
Хотя, если он уже проник, то ему мало что помешает. Поэтому следует быть очень внимательным и предусмотрительным при разработке систем безопасности, пускай даже, простенького многопользовательского сайта.
Продолжение следует…
© Владислав Демьянишин
Вы находитесь на официальном сайте Владислава Демьянишина - разработчика игры Dune IV (Dune 4). На нашем сайте Вы можете бесплатно скачать игры Dune IV (Dune 4), Battle City (Танчики с Dendy/Nintendo), читы к играм и многое другое. Также Вы можете скачать бесплатно программы и полезные утилиты. Все программы чистые, т.е. не содержат вирусов и иного вредоносного ПО.
Журнал > Программирование > PHP и WEB для новичков (HTML, JavaScript, PHP, MySQL) > PHP и WEB для новичков (часть 14): Авторизация и безопасность
| ||||||||||||||||||
|
||||||||||||||||||