Тема: HTTP Authentication в PHP запущеном как CGI/FastCGI/SuExec
Способ подключения PHP не как SAPI достаточно распространен и удобен, но как и во всем есть нюансы. Я хочу рассказать как можно реализовать такую нужную штуку как HTTP Basic Authentication.
прелюдия
HTTP Basic Authentication - это возможность ограничить доступ к какому-либо http ресурсу (обсуждаем только apache), тоесть тупо попросить логин и пасс. По правилам это делается так
В файлик, например, .htpasswd записывается пароль в виде webuser:qkbPmuht5Gzgc - это md5 алгоритмом зашифрованй пароль, системная функция crypt(). UNIX неумеет хранить пароли в plaintext формате, а вот Windows умеет. Дальше в .httaccess файл записывается что-то подобное
AuthType Basic
AuthUserFile "/home/username/path_to_htpasswd/.htpasswd"
AuthName “Enter valid username and password!”
require valid-user
<Files my-secret-file.html>
require valid-user
</Files>
и при обращении к данной директории и всем нижестоящим или файлу как в примере будет автоматически потребован пароль. Это очень удобно так как ненужно делать никаких html форм.
Проблема
Точно такой же принцип может применяться и в PHP скриптах для ограничения доступа к какому-либо файлу. НО! это все работает только если PHP подсоединен как SAPI (mod_php) модуль.
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello, </p>".$_SERVER['PHP_AUTH_USER'];
echo "<p>You entered as your password: </p>".$_SERVER['PHP_AUTH_PW'];
}
?>
Вот этот код заставит при вызови скрипта открыть диалоговое окно и попросить логин и пасс, которые в последствии передадутся в переменные $_SERVER['PHP_AUTH_USER'] и $_SERVER['PHP_AUTH_PW']
Все замечательно и красиво, но работает только с mod_php, грустно!
Решение
В решении этой проблемы может помочь mod_rewrite, вообще очень мощная штука при правильном использовании. Для того чтобы перенаправить в скрипт данные из формы мы используетм вот такое правило в .htaccess файле
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>
Но этого недостаточно, так как данные находятся в несколько неприемлемом формате, поэтому их нужно обработать
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
после этого переменные $_SERVER['PHP_AUTH_USER'] и $_SERVER['PHP_AUTH_PW'] содержат всю необходимую информацию. Вот работающий пример
<?php
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello, </p>".$_SERVER['PHP_AUTH_USER'];
echo "<p>You entered as your password: </p>".$_SERVER['PHP_AUTH_PW'];
}
?>