Задача
Необходимо использовать PHP для защиты разделов веб сайта с помощью паролей. Вместо того чтобы хранить пароли во внешнем файле и возлагать на сервер функции проверки регистрационной информации пользователей, надо реализовать логику проверки паролей в PHP программе
Решение
Глобальные переменные $_SERVER['PHP_AUTH_USER'] и $_SERVER['PHP_AUTH_PW'] хранят предоставленные пользователем имя и пароль. Для того чтобы закрыть доступ к странице, пошлите заголовок WWW-Authenticate, обозначающий область (realm) аутентификации, вместе с кодом состояния 401:
header('WWWAuthenticate: Basic realm="My Website" ');
header('HTTP/1.0 401 Unauthorized');
echo "Нужно ввести верный логин и пароль.";
exit;
Обсуждение
Увидев заголовок 401, броузер показывает диалоговое окно для ввода имени пользователя и пароля. Если это удостоверение личности (имя пользователя и пароль) принимается сервером, то оно ассоциируется с областью, указанной в заголовке WWW Authenticate. Код, который проверяет удостоверение личности (credentials), должен быть выполнен раньше, чем будет послан какой-либо вывод в броузер, т. к. может быть послан заголовок. Например, это можно сделать с помощью функции, подобной pc_validate(), которая показана в примере 8.2.
Пример 8.2. pc_validate()
function pc_validate($user,$pass) {
/* замените на соответствующую проверку имени пользователя и пароля, например на проверку в базе данных */>
$users = array('david' => 'fadj', 'adam' => '8HEj838');
if (isset($users[$user]) && ($users[$user] == $pass))
{ return true; }
else { return false; } }
Ниже приведен пример применения функции pc_validate():
if (! pc_validate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
header('WWW Authenticate: Basic realm="My Website"');
header('HTTP/1.0 401 Unauthorized');
echo "Нужно ввести верный логин и пароль.";
exit; }
Замените содержание функции pc_validate() на вашу собственную логику проверки правильности ввода пароля пользователем. Можно так же заменить строку области «My Website», а также сообщение «You need to enter a valid username and password», появляющееся при нажатии пользователем кнопки «cancel» в диалоговом окне аутентификации его броузера.
Нельзя применять базовую аутентификацию HTTP, если PHP используется в качестве CGI. Если нельзя исполнять PHP как серверный модуль, то можно обратиться к аутентификации на основе cookies.
Другая особенность базовой аутентификации HTTP заключается в том, что она не предоставляет другого способа выхода пользователя из сеанса, кроме закрытия броузера.
Однако есть прямой путь заставить пользователя завершить работу по истечении фиксированного интервала времени: включить вычисление
времени в строку области. Броузеры проверяют одну и ту же комбинацию пользовательского имени и пароля каждый раз, когда они запрашивают удостоверение личности в той же самой области. Изменение имени области принуждает броузер запрашивать у пользователя но вые идентификационные данные. Например, следующий код вызывает принудительный выход каждую полночь:
if (! pc_validate($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])) {
$realm = 'My Website for '.date('Y m d');
header('WWW Authenticate: Basic realm="'.$realm.'"');
header('HTTP/1.0 401 Unauthorized');
echo "Нужно ввести верный логин и пароль.";
exit;
}
Можно также определить время выхода для каждого пользователя, не изменяя при этом имя области, путем сохранения времени регистрации пользователя или времени его доступа к защищенной странице.
Функция pc_validate2() записывает время регистрации в базу данных и вызывает принудительный выход, если прошло более 15 минут с момента последней регистрации пользователя на защищенной странице.
Пример 8.3. pc_validate2()
Function pc_validate2($user,$pass) {
$safe_user = strtr(addslashes($user),array('_' => '\_', '%' => '\%'));
$r = mysql_query("SELECT password,last_access
FROM users WHERE user LIKE '$safe_user'");
if (mysql_numrows($r) == 1) {
$ob = mysql_fetch_object($r);
if ($ob >password == $pass) {
$now = time();
if (($now $ob >last_access) > (15 * 60)) {
return false;
} else {
// обновление времени последнего доступа
mysql_query("UPDATE users SET last_access = NOW()
WHERE user LIKE '$safe_user'");
return true;
}
}
} else {
return false;
}
}
Например:
if (! pc_validate($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])) {
header('WWW Authenticate: Basic realm="My Website"');
header('HTTP/1.0 401 Unauthorized');
echo "Нужно ввести верный логин и пароль.";
exit;
}