Бессильный auth php. HTTP Установка защиты на страницу используя MySQL и PHP
Возможно использовать функцию header() для отправки сообщения "Authentication Required" браузеру, заставив его показать окошко для ввода логина и пароля. Как только пользователь заполнит логин и пароль, ссылка, содержащая PHP-скрипт будет вызвана еще раз с предопределенными переменными PHP_AUTH_USER , PHP_AUTH_PW , и AUTH_TYPE , установленными в логин, пароль и тип аутентификации соответственно. Эти предопределенные переменные хранятся в массивах $_SERVER и $HTTP_SERVER_VARS . Поддерживаются оба типа: "Basic" и "Digest" (начиная с версии PHP 5.1.0). Подробнее смотрите функцию header() .
Пример фрагмента скрипта, который вынуждает клиента авторизоваться для просмотра страницы:
Пример #1 Пример Basic HTTP-аутентификации
if (!isset($_SERVER
[
"PHP_AUTH_USER"
])) {
header
("WWW-Authenticate: Basic realm="My Realm""
);
echo
"Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel"
;
exit;
} else {
echo
"
Hello { $_SERVER [ "PHP_AUTH_USER" ]} .
" ;echo "
Вы ввели пароль
{ $_SERVER [ "PHP_AUTH_PW" ]} ." ;}
?>
Пример #2 Пример Digest HTTP-аутентификации
Это пример реализации простого скрипта Digest HTTP-аутентификации. За подробностями обращайтесь к » RFC 2617 .
$realm = "Запретная зона" ;
//user => password
$users
= array("admin"
=>
"mypass"
,
"guest"
=>
"guest"
);
if (empty($_SERVER
[
"PHP_AUTH_DIGEST"
])) {
header
("HTTP/1.1 401 Unauthorized"
);
header
("WWW-Authenticate: Digest realm=""
.
$realm
.
"",qop="auth",nonce=""
.
uniqid
().
"",opaque=""
.
md5
($realm
).
"""
);
Die("Текст, отправляемый в том случае, если пользователь нажал кнопку Cancel"
);
}
// анализируем переменную PHP_AUTH_DIGEST
if (!($data
=
http_digest_parse
($_SERVER
[
"PHP_AUTH_DIGEST"
])) ||
!isset($users
[
$data
[
"username"
]]))
die("Неправильные данные!"
);
// генерируем корректный ответ
$A1
=
md5
($data
[
"username"
] .
":"
.
$realm
.
":"
.
$users
[
$data
[
"username"
]]);
$A2
=
md5
($_SERVER
[
"REQUEST_METHOD"
].
":"
.
$data
[
"uri"
]);
$valid_response
=
md5
($A1
.
":"
.
$data
[
"nonce"
].
":"
.
$data
[
"nc"
].
":"
.
$data
[
"cnonce"
].
":"
.
$data
[
"qop"
].
":"
.
$A2
);
if ($data
[
"response"
] !=
$valid_response
)
die("Неправильные данные!"
);
// ok, логин и пароль верны
echo
"Вы вошли как: "
.
$data
[
"username"
];
// функция разбора заголовка http auth
function
http_digest_parse
($txt
)
{
// защита от отсутствующих данных
$needed_parts
= array("nonce"
=>
1
,
"nc"
=>
1
,
"cnonce"
=>
1
,
"qop"
=>
1
,
"username"
=>
1
,
"uri"
=>
1
,
"response"
=>
1
);
$data
= array();
$keys
=
implode
("|"
,
array_keys
($needed_parts
));
Preg_match_all ("@(" . $keys . ")=(?:([\""])([^\2]+?)\2|([^\s,]+))@" , $txt , $matches , PREG_SET_ORDER );
Foreach ($matches
as
$m
) {
$data
[
$m
[
1
]] =
$m
[
3
] ?
$m
[
3
] :
$m
[
4
];
unset($needed_parts
[
$m
[
1
]]);
}
Return
$needed_parts
?
false
:
$data
;
}
?>
Замечание : Замечание касательно совместимости
Будьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы гарантировать максимальную совместимость с наибольшим количеством различных клиентов, слово "Basic" должно быть написано с большой буквы "B", регион (realm) должен быть взят в двойные (не одинарные!) кавычки, и ровно один пробел должен предшествовать коду 401 в заголовке HTTP/1.0 401 . Параметры аутентификации должны разделяться запятыми, как это было показано в примере Digest аутентификации выше.
Вместо простого отображения на экране переменных PHP_AUTH_USER и PHP_AUTH_PW , вам, возможно, понадобится проверить их корректность. Используйте для этого запрос к базе данных или поиск пользователя в dbm-файле.
Вы можете пронаблюдать особенности работы браузера Internet Explorer. Он очень требователен к параметру передаваемых заголовков. Трюк с указанием заголовка WWW-Authenticate перед отправкой статуса HTTP/1.0 401 пока что работает для него.
Для того, чтобы предотвратить написание кем-либо скрипта, раскрывающего пароль к странице, которая использует внешнюю аутентификацию, переменные PHP_AUTH не устанавливаются в случае, если данная страница использует внешнюю аутентификацию и установлен безопасный режим . Несмотря на это, переменная REMOTE_USER может использоваться для аутентификации пользователя, прошедшего внешнюю аутентификацию. Таким образом, вы всегда можете воспользоваться переменной $_SERVER["REMOTE_USER"] .
Замечание : Замечание касательно конфигурации
PHP использует указание директивы AuthType для указания того, используется внешняя аутентификация или нет.
Следует заметить, что все вышесказанное не предотвращает похищения паролей к страницам, требующим авторизацию, кем-либо, кто контролирует страницы без авторизации, расположенные на том же сервере.
И Netscape Navigator и Internet Explorer очищают кэш аутентификации текущего окна для заданного региона (realm) при получении от сервера статуса 401. Это может использоваться для реализации принудительного выхода пользователя и повторного отображения диалогового окна для ввода имени пользователя и пароля. Некоторые разработчики используют это для ограничения авторизации по времени или для предоставления кнопки "Выход".
Пример #3 Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль
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
"
"
;
echo
"Предыдущий логин: "
.
htmlspecialchars
($_REQUEST
[
"OldAuth"
]);
echo
";
echo
"\n"
;
echo
".
htmlspecialchars
($_SERVER
[
"PHP_AUTH_USER"
]) .
"\" />\n"
;
echo
"\n"
;
echo
"
}
?>
Это поведение не регламентируется стандартами HTTP Basic -аутентификации, следовательно, вы не должны зависеть от этого. Тестирование браузера Lynx показало, что Lynx не очищает кэш авторизации при получении от сервера статуса 401, и, нажав последовательно "Back", а затем "Forward" возможно открыть такую страницу, при условии, что требуемые атрибуты авторизации не изменились. Однако, пользователь может нажать клавишу "_" для очистки кеша аутентификации.
Для того, чтобы добиться корректной работы HTTP-аутентификации в IIS сервере с CGI версией PHP, вы должны отредактировать конфигурационную настройку IIS под названием "Directory Security ". Щелкните на надписи "Edit " и установите опцию "Anonymous Access ", все остальные поля должны остаться неотмеченными.
Замечание : Замечание касательно IIS:
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации PHP опция cgi.rfc2616_headers должна быть установлена значением 0 (значение по умолчанию).
Замечание :
В случае, если используется безопасный режим , UID текущего скрипта будет добавлен в realm -часть заголовка WWW-Authenticate .
Иногда бывает нужно закрыть от постороннего доступа PHP страницу, если Вы делаете закрытую область сайта. Это может быть какая-то скрытая информация для ваших клиентов или посетителей сайта, какой-то администраторский интерфейс для вас и т.д. Можно придумать сотни различных задач требующих ограничения доступа.
Закрыть такую страницу можно несколькими взаимодополняющими друг друга способами:
- Защита паролем (логин/пароль) с помощью переменных $_SERVER["PHP_AUTH_USER"] и $_SERVER["PHP_AUTH_PW"] .
- Защита по IP адресу клиента с помощью переменной $_SERVER["REMOTE_ADDR"] .
- Защита по MAC адресу в локальных сетях (дополнительно к защите по IP ).
Разберем сначала первый способ, который является основным. Он позволяет закрыть доступ к странице по логину и паролю, таким образом доступ могут получить только люди знающие логин и пароль. К тому же их можно разделять по этому признаку и выдавать соответственно разную информацию для каждого. Реализуется с помощью выдачи специальных полей в заголовке протокола HTTP . Создадим функцию auth_send() :
" ,"
Ошибка аутентификации
" ,"Обратитесь к администратору для получения логина и пароля.
" ,""; exit; }; ?>Эту функция сообщает браузеру о том, что для доступа нужна авторизация по логину и паролю. И выдает также страницу в HTML для пользователя.
" ,"
Добро пожаловать!
" ,"Вы зашли по логину ",$auth_user," и паролю ",$auth_pass,".
" ,""; ?>Код проверки логина и пароля не слишком сложный в данном случае, так как реализован для одного человека. Логика работы проста, если нет переменной $_SERVER["PHP_AUTH_USER"] и $_SERVER["PHP_AUTH_PW"] или их значения не совпадают с нужными, то вызываете функцию auth_send() . Не забывайте, что в ней в конце вызывается exit , поэтому выполнение программы прекращается.
Следующая ступень защиты реализуется по фильтрации IP адреса подключающегося клиента. Конечно в интернете многие провайдеры выдают IP адреса на время и эту защиту использовать бесполезно, но если речь идет о корпоративных локальных сетях, то данная проверка обеспечит дополнительную защиту.
Ваш IP не найден!!!"; exit; }; ?>
Тут в строке $allowed_ips через пробел указаны IP адреса, которым разрешен доступ. Далее получаем массив с помощью explode() и делаем поиск адреса клиента из $_SERVER["REMOTE_ADDR"] . Я для поиска применил функцию array_search() , так как неверняка ее код реализованный на Си будет работать несколько быстрее, чем то, что мы можем написать на PHP с помощью циклов for или foreach . Но скорость тут не главное:)
И последняя ступень защиты это проверка MAC адреса. Она относится к разряду параноидальных и ее стоит использовать, если вы получаете доступ из локальной сети и данные, которые вы защищаете действительно очень важные. Я пока реализовал эту проверку только на системе Linux , в силу относительной простоты реализации. Но Вы можете ее попробовать реализовать под любую другую платформу. Пишем функцию:
Как линуксоиды уже поняли она основана на ARP таблице системы, доступ к которой можно получить с помощью файла /proc/net/arp . Функция ищет по строкам требуемый IP адрес и возвращает его MAC адрес:
Ваш IP=192.168.10.15 и MAC=00:04:31:E4:F8:37
В системе Windows возможно тоже есть какие-то способы получить MAC попроще, но из тех, которые реально работают, это вывод ARP таблицы системы командой:
C:\WINDOWS\>arp -a Интерфейс: 192.168.10.15 on Interface 0x1000003 Адрес IP Физический адрес Тип 192.168.10.1 00-50-22-b0-6a-aa динамический 192.168.10.2 00-0f-38-68-e9-e8 динамический 192.168.10.3 00-04-61-9e-26-09 динамический 192.168.10.5 00-0f-38-6a-b1-18 динамический
Реализовать защиту на основе этого адреса Вы сможете сами, если Вам это действительно надо:) Но помните, что если у Вас в сети неуправляемое оборудование без возможности привязки MAC адреса к порту, эта защита может не сработать, так как можно подделать все Ваши идентификационные данные используемые для защиты (логин, пароль, IP и MAC адрес).