HTTP-Аутентификация в PHP
HTTP-Аутентификация в PHP возможна только в том случае, когда он выполняется
как модуль веб-сервера Apache, и, соответственно, недоступна для CGI-версии.
Ваш скрипт может использовать функцию header() для того,
чтобы отправить браузеру клиента сообщение "Authentication Required",
что в свою очередь приведет к появлению диалогового окна для ввода имени
пользователя и пароля. После того как клиент ввел свое имя и пароль,
скрипт будет вызван повторно, но уже с
предопределенными переменными
PHP_AUTH_USER, PHP_AUTH_PW
и AUTH_TYPE, которые соответственно содержат
имя пользователя, пароль и тип аутентификации. Эти переменные могут быть
найдены в массиве $_SERVER и
$HTTP_SERVER_VARS. В настоящее время поддерживается только
"Basic"-аутентификация. Также вы можете ознакомится с более детальным
описанием функции header().
Замечание:
Замечание касательно версии PHP
Cуперглобальные переменные,
такие как $_SERVER, доступны,
начиная с » 4.1.0.
Массив $HTTP_SERVER_VARS доступен в PHP 3 и выше.
Пример фрагмента скрипта, который вынуждает клиента авторизироваться для
просмотра страницы:
Пример #1 Пример HTTP-аутентификации
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>Вы ввели пароль {$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>
Замечание:
Замечание касательно совместимости
Будьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы
гарантировать максимальную совместимость с наибольшим количеством
различных клиентов, слово "Basic" должно быть написано с большой буквы "B",
регион (realm) должен быть взят в двойный (не одинарные!) кавычки,
и ровно один пробел должен предшествовать коду 401 в заголовке
HTTP/1.0 401.
Вместо простого отображения на экране переменных PHP_AUTH_USER
и PHP_AUTH_PW, вам, возможно, понадобится
проверить их корректность. Используйте для этого запрос к базе
данных или поиск пользователя в dbm-файле.
Вы можете пронаблюдать особенности работы браузера Internet Explorer.
Он очень требователен к параметру передаваемых заголовков. Указание
заголовка WWW-Authenticate перед отправкой статуса
HTTP/1.0 401 является небольшой хитростью.
Начиная с PHP 4.3.0, для того, чтобы предотвратить написание
кем-либо скрипта, раскрывающего пароль к странице, которая использует
внешнюю аутентификацию, переменные PHP_AUTH
не устанавливаются в случае, если данная страница использует
внешнюю аутентификацию и установлен безопасный режим. Несмотря на это,
переменная REMOTE_USER может использоваться для
аутентификации пользователя, прошедшего внешнюю аутентификацию.
Таким образом, вы всегда можете воспользоваться переменной
$_SERVER['REMOTE_USER'].
Замечание:
Замечание касательно конфигурации
PHP использует указание директивы AuthType для
указания того, используется внешняя аутентификация или нет.
Следует заметить, что все вышесказанное не предотвращает похищения паролей к
страницам, требующим авторизацию, кем-либо, кто контролирует страницы без
авторизации, расположенные на том же сервере.
И Netscape Navigator и Internet Explorer очищают кеш аутентификации
текущего окна для заданного региона (realm) при получении от сервера.
Это может использоваться для реализации принудительного выхода пользователя
и повторного отображения диалогового окна для ввода имени пользователя и
пароля. Некоторые разработчики используют это для ограничения авторизации по
времени или для предоставления кнопки "Выход".
Пример #2 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль
<?php
function authenticate() {
header('WWW-Authenticate: Basic realm="Test Authentication System"');
header('HTTP/1.0 401 Unauthorized');
echo "Вы должны ввести корректный логин и пароль для получения доступа к ресурсу \n";
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER']) ||
($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
}
else {
echo "<p>Добро пожаловать: {$_SERVER['PHP_AUTH_USER']}<br />";
echo "Предыдущий логин: {$_REQUEST['OldAuth']}";
echo "<form action='{$_SERVER['PHP_SELF']}' METHOD='post'>\n";
echo "<input type='hidden' name='SeenBefore' value='1' />\n";
echo "<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}' />\n";
echo "<input type='submit' value='Авторизоваться повторно' />\n";
echo "</form></p>\n";
}
?>
Это поведение не регламентируется стандартами HTTP Basic-аутентификации,
следовательно, вы не должны зависеть от этого. Как показали тесты,
браузер Lynx не очищает кеш авторизации при получении от сервера
статуса 401, и, нажав последовательно "Back", а затем "Forward" возможно
открыть такую страницу, при условии, что требуемые атрибуты авториазации не изменились.
Однако, пользователь может нажать клавишу '_' для очистки кеша аутентификации.
Также следует заметить, что до версии PHP 4.3.3, HTTP-аутентификация
не работала на серверах под управлением Microsoft IIS, если PHP был установлен
как CGI-модуль, в силу некоторых ограничений IIS. Для того, чтобы
добиться корректной работы в PHP 4.3.3+, вы должны отредактировать
конфигурационную настройку IIS под названием "Directory Security".
Щелкните на надписи "Edit" и установите опцию "Anonymous Access",
все остальные поля должны остаться неотмеченными.
Еще одно ограничение, если вы используете IIS посредством ISAPI: переменные
PHP_AUTH_* не определены, но в то же время доступна
переменная HTTP_AUTHORIZATION. Пример кода, который вы могли бы
использовать: list($user, $pw) = explode(':',
base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
Замечание:
Замечание касательно IIS:
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации
PHP опция cgi.rfc2616_headers должна
быть установлена значением 0 (значение по умолчанию).
Замечание:
В случае, если используется защищенный режим,
UID текущего скрипта будет добавлен в realm-часть заголовка
WWW-Authenticate.