Статья в рамках программы переноса материалов со старого сайта.
Базовая аутентификация - простейший вид защиты каталогов на сайте. Но не смотря на её простоту, она достаточно надежна для того, чтобы спать спокойно, не опасаясь за сокровища, которые хранятся на сайте. Правда есть одна тонкость. Если PHP стоит не как модуль, а как CGI, то такая аутентификация работать не будет. Увы.
Давайте рассмотрим, как это можно сделать.
Вариант 1. Защита подключаемым файлом
Раз мы не используем базу данных, то значит аутентификационные данные будут хранится в файле. Чтобы они не стали достоянием общественности, файл должен быть исполняемым, то есть иметь расширение .php Очень удобно хранить данные в виде массива, потому что сразу видна принадлежность пароля к логину. Пароль от греха лучше захэшировать, хуже от этого точно не станет. Чтобы это сделать, можно просто выполнить такой код:
1
2
3
4
5
6
|
<?php
echo md5('тут_пароль');
|
Ну или использовать другой алгоритм хэшировния. Сейчас важно не это, важен сам принцип аутентификации. То, что получится, и есть хэш.
Теперь собственно сам массив. Можно в него добавлять кучу данных, по числу доверенных лиц.
Логин => хэш пароля.
1
2
3
4
5
6
7
8
9
10
|
<?php
$admins = array( 'root' => '63a9f0ea7bb98050796b649e85481845', // root => root 'admin' => 'e10adc3949ba59abbe56e057f20f883e', );
|
Положим этот массив в файл auth.php
Теперь приступим, собственно, к созданию файла, который будет отвечать за аутентификацию. Для этого вида авторизации нужно отослать браузеру клиента такие заголовки:
1
2
3
|
WWW-Authenticate: Basic realm=\"Подпись на окне\" HTTP/1.0 401 Unauthorised
|
Браузер выдаст окошко для ввода логина и пароля. Введённые данные будут помещены в суперглобальный массив: логин в элемент суперглобального массива
$_SERVER['PHP_AUTH_USER'],
а пароль - в
$_SERVER['PHP_AUTH_PW'].
Теперь можно посмотреть это в деле. Тоесть, если пользователь не авторизован, то наш сценарий посылает ему запрос на авторизацию:
1
2
3
4
5
6
7
8
9
10
|
<?php
if(empty($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="Administrative resource"'); header("HTTP/1.0 401 Unauthorised"); exit(); }
|
Окошко получено, теперь нужно сравнить то, что в него будет введено, с тем, что имеется в файле с данными.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?php // Подключаем файл с аутентификационными данными include './auth.php';
// Устанавливаем ключ входа $key = false; // Сверем данные аутентификации с полученными от юзера if(isset($admins[$_SERVER['PHP_AUTH_USER']]) && md5($_SERVER['PHP_AUTH_PW']) === $admins[$_SERVER['PHP_AUTH_USER']]) $key = true;// Если пара совпала, переустанавливаем ключ
|
Ну а что бы не посылать сразу лесом, если человек ошибся, выдадим ему окошко еще раз.
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php // Если ключа так и нет, опять окно и стоп-машина. if(empty($key)) { // опять выдаем юзеру это окошко, что бы заполнил header('WWW-Authenticate: Basic realm="Administrative resource"'); header ('HTTP/1.0 401 Unauthorized'); exit();
}
|
Ну и соберем теперь все это в кучу:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<?php
if(empty($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="Administrative resource"'); header("HTTP/1.0 401 Unauthorised"); exit(); }
include './auth.php'; $key = false; if(isset($admins[$_SERVER['PHP_AUTH_USER']]) && md5($_SERVER['PHP_AUTH_PW']) === $admins[$_SERVER['PHP_AUTH_USER']]) $key = true;
if(empty($key)) { header('WWW-Authenticate: Basic realm="Administrative resource"'); header ('HTTP/1.0 401 Unauthorized'); exit();
}
|
Теперь стоит поместить эти строки в начала любого файла и доступ к нему будет ограничен узкому кругму лиц.
Вариант 2. Защита подключаемым файлом с использованием БД
Она почти не отличается от той, которую мы только что рассмотрели. Разница в том, что данные будут хранится не в файле, а в базе данных
Первым делом нужно создать MySQL-таблицу, где будут храниться логины админов и их пароли. Таблица будет такая:
1
2
3
4
5
6
|
CREATE TABLE `admin` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `user` VARCHAR(50) NOT NULL, `password` TINYTEXT NOT NULL, PRIMARY KEY (`id`) );
|
Теперь занесём данные в таблицу (пароль шифруем так же, как и раньше):
1
|
INSERT INTO `admin` ( `id` , `user` , `password` ) VALUES ('', 'admin', '21232f297a57a5a743894a0e4a801fc3');
|
При желании в дальнейшем можно будет добавить ещё пользователей. Но пока только один. 'admin' => 'admin'
Теперь выведем в нашей программе запрос к базе данных при введении логина и пароля, экранируя специальные символы для этого запроса при вводе логина. Пароль экранировать не нужно, функция md5() (или любя другая функция хэшировния пароля) не пустит ничего лишнего.
Нужно помнить о магических кавычках, иначе будет двойное экранирование.
А если при выборке в таблице не будет обнаружено записи по заданным условиям, то снова покажем окно для авторизации:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<?php
// Коннект лучше использовть общий для сайта $link = mysqli_connect('localhost', 'root', '', 'DBname') or die('No connect'); mysqli_set_charset($link, 'utf8'); /////////////////////////////////////////////////// if(empty($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="Administrative resource"'); header("HTTP/1.0 401 Unauthorised"); exit(); }
$res = mysqli_query($link, "SELECT COUNT(*) AS `cnt` FROM `admin` WHERE `user` = '". mysqli_real_escape_string($link,
$_SERVER['PHP_AUTH_USER']) ."' AND `password` = '". md5($_SERVER['PHP_AUTH_PW']) ."'" ); $data = mysqli_fetch_assoc($res);
if (empty($data['cnt'])) { header('WWW-Authenticate: Basic realm="Administrative resource"'); header ("HTTP/1.0 401 Unauthorized"); exit(); }
|
Ну а дальше все точно так же, пишем это первыми строками и спим спокойно.
Вариант 3. Защита при помощи .htaccess и .htpasswd.
В данном случае нужно создать два файла: один .htaccess, другой - с логинами и паролями. Первый файл положим в директорию, доступ к которой нужно ограничить.
Что в нем?
Строчка "AuthType Basic" будет указывать метод шифровки пароля.
"AuthName "Надпись в окошке" " - здесь просто указывается, какая надпись будет выдана в форме.
"AuthUserFile /путь к файлу/.htpasswd" - путь к файлу с паролями. Общепринято называть такие файлы .htpasswd (хотя это и не обязательно).
"require valid-user" - эта строка сообщает, что доступ к директории будет открыт всем пользователям, чьи логины и пароли есть в .htpasswd-файле. Чтобы, к примеру, дать доступ конкретным пользователям (например, Admin), нужно написать "Require user Admin" (остальных, если потребуется, можно указать через пробел).
Итак, у нас получился .htaccess-файл такого вида:
1
2
3
4
|
AuthType Basic AuthName "Administrative resource" AuthUserFile /путь к файлу/.htpasswd require valid-user
|
Теперь нужно создать файл с паролями. Создаётся он при помощи утилиты htpasswd (файл htpasswd.exe), входящей в состав сервера Apache и лежащей в папке bin.
По сути это обычный текстовой файл, однако создать его вручную не получится - пароль хранится в зашифрованном виде, а шифровку реализует как раз эта самая программка.
Примечание. Если у Вас стоит пакет Денвер, то в нем нет такой утилиты. Выход прост. Берем её здесь, рспаковываем и складываем по пути Z:\usr\local\apache\ Теперь все готово.
|
В Windows можно добраться до htpasswd, используя, например, Total или Windows Commander.
Нужно перейти в директорию, где хранится утилита, и набрать в командной строке это:
1
|
htpasswd -cm .htpasswd admin
|

Жмем "enter", получаем такое окошко:

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

Это будет текстовой файл внутри которого храниться логин и через двоеточие зашифрованный пароль. Вот так:
1
|
admin:$apr1$qf3.....$2xWCAZSUuAVXrnsnW4D071
|
Если встанет необходимость добавить в файл ещё логины с паролями, то надо проделать ту же самую процедуру, но из команды на создание нового логина просто убрать ключ "с". Вот так:
1
|
htpasswd -m .htpasswd admin2
|
Теперь этот файл нужно взять и положить туда, куда задумывалось с самого начала:
1
2
3
4
|
AuthType Basic AuthName "Administrative resource" AuthUserFile /путь к файлу/.htpasswd require valid-user
|
Место для этого файла лучше выбирать выше корневой директории, куда нет доступа по протоколу HTTP. Но если нет такой возможности, то лучше положить его в отдельную папку и защитить тем же самым сервером, положив в неё .htaccess такого содержания:
1
2
3
|
<Files .htpasswd> deny from all </Files>
|
Ну вот и все, пробуйте. И спокойного, крепкого сна :)
Винокуров Александр aka A.V.
Роман