| АВТОРИЗАЦІЯ ЗА ДОПОМОГОЮ ЗАГОЛОВКА
У РНР є команда Header - вона дозволяє відправити браузеру відвідувача, що запитав сторінку з тим, що містить цю команду сценарієм, певну службову інформацію - так званий "заголовок". Існує досить багато варіантів заголовків (наприклад, заголовок "Location: http://адрес" приведе кперенаправ-ленію на вказаний URL; те ж саме, що і при використанні мета-тэга http-equiv з параметром "Refresh"), проте для авторизації нам буде потрібно заголовок "Www-authenticate".
Примітка:
Заголовок - це дані, передавані браузеру до передачі самої web-страницы, повідомляючі йому деякі параметри передаваного файлу іпі певні команди. Список всіх можливих заголовків, які зобов'язані підтримувати сучасні браузери, можна знайти в специфікаціях протоколу HTTP - вони є, наприклад, на сайті http://www.w3.org. PHP-команда Header виконує всього одну дію - вона просто передає те, що вказане в її параметрі, в браузер, що запитав сторінку, на якій вона знаходиться, як заголовок.
Слід пам'ятати, що заголовок повинен передаватися в браузер до будь-якого іншого виводу в нього, за винятком установки cookie.
В тому випадку, якщо браузер отримує заголовок "Www-authenticate", то він видає відвідувачеві стандартне вікно для введення логіна і пароля, яке ви напевно багато раз бачили (ріс.8.2). Як тільки відвідувач натискує кнопку Ok цього вікна, браузер знов заходить на ту сторінку, з якою цей заголовок був йому посланий, але цього разу вже передає сценарію на цій сторінці дві змінні - те, що було введене в поля введення логіна і пароля. Web-сервер дає цим змінним імена $PHP_AUTH_USER і $PHP_AUTH_PW, і їх стає можна використовувати в останніх сценаріях на сторінці як будь-які інші змінні - використовувати у виразах, порівнювати
з яким-небудь еталоном, привласнювати їм які-небудь інші значення, нарешті.
Якщо відвідувач натискує кнопку Cancel в діалоговому вікні запиту логіна і пароля, то виконання коди сторінки просто продовжується з наступної строчки за командою Header. Жодні змінні сторінці не передаються.
Проте змінні $PHP_AUTH_USER і $PHP_AUTH_PW - не прості. Якщо вони один раз були визначені, то згодом вони передаються всім web-страницам, які завантажуються в те ж саме вікно браузера, де сталася авторизація! Іншими словами, якщо по якихось причинах потрібно перевіряти логін і пароль відвідувача на кожній із сторінок сайту (скажімо, виводити різну інформацію авторизованим і неавторизованим відвідувачам), то кожного разу запрошувати ці дані не потрібно - досить використовувати значення змінних $PHP_AUTH_USER і $PHP_AUTH_PW. Значення даних змінних втрачаються в разі закриття вікна браузера, в якому спочатку сталася авторизація (а в інші вікна вони і не передаються). При виході за межі віртуального сервера, на якому сталася авторизація (зазвичай його кордони збігаються з кордонами ак-каунта), дані змінні перестають передаватися сторінкам, проте при повторному вході на вихідну адресу знов стають доступними (це забезпечення безпеки - за межами вашого віртуального сервера логіни і паролі ваших відвідувачів ніхто взнати з їх браузеров не зможе).
До
речі, при використанні попереднього способу - засобами Apache - в змінні $PHP_AUTH_USER і $PHP_AUTH_PW теж поміщаються значення логіна і пароля, введені користувачем. В принципі ви можете знайти їм яке-небудь вживання.
Наприклад, пригадаємо вміст сьомої глави, в якій розглядалася програма для самостійного завантаження відвідувачами файлів на сайт. Пам'ятаєте, в чому була проблема - перевірка пароля і саме завантаження файлів здійснювалися сценарієм на одній і тій же сторінці, і в разі помилки при введенні пароля відвідувач все одно був вимушений чекати закінчення завантаження файлу на сайт, щоб той був відразу ж звідти видалений? Так от - використовуючи даний спосіб авторизації (і попередній - засобами Apache - теж), можна розділити авторизацію і закачування файлів, надавши відвідувачеві можливість спочатку ввести логін з паролем, а лише потім, якщо вони правильні, видати йому форму для закачування файлу. Якщо додати на сторінку обробки закачаного файлу коротку програму для перевірки змінних $PHP_AUTH_USER і $PHP_AUTH_PW, то можна не боятися заходу на сторінку завантаження неавторизованих відвідувачів (скажімо, по закладці або шляхом прямого набору її адреси в браузере) - такі будуть відсіяні, а запити легальних оброблені.
Нижче приводиться сценарій, який запрошує у користувача логін і пароль, перевіряє їх по наявності в певному файлі, а потім виводить або запрошення до завантаження файлу, або повідомлення про відмову в авторизації.
Отже, початок сценарію. Звернете увагу, що для того, щоб він спрацював до команди Header у видаваний документ не повинно нічого виводитися: ні результат виконання команд РНР, ні простий вміст сторінки, - так вже сприймають web-страницы браузери. Зокрема, даний сценарій повинен розташовуватися на самому початку сторінки, і символи <?php мають бути на ній найпершими, перед ними не повинно бути навіть пропуску.
<?php
Оскільки після видачі вікна авторизації браузер знов викликає web-страницу, передаючи їй авторизаційні дані, то можна перевірити їх ще до відправки браузеру "заголовка Www-authenticate. Насправді - якщо вікно авторизації не виводилося взагалі, то змінні $PHP_AUTH_USER $PHP_AUTH_PW будуть порожніми (вірніше, взагалі не визначені), а якщо виводилося - те в них виявиться інформація, введена відвідувачем (тобто логін і пароль).
Найбільш простим варіантом буде вказівка логіна і пароля в тексті самої програми авторизації - адже все одно код на РНР, що розміщується на сторінці, відвідувачі побачити не смогут1. В цьому випадку команда перевірки вмісту змінних $PHP_AUTH_USER і $PHP_AUTH_PW на відповідність вказаним виглядатиме як
if (($PHP_AUTH_USER!="login")||($PHP_AUTH_PW!= "parol"))
Далі йде той код, який виконується в разі невідповідності вмісту змінних вказаним в команді логіну і паролю. В разі найпершого завантаження сторінки він, природно, теж ви-
Вірніше, зможуть лише в тому випадку, якщо даний код розташовується у фаше не з тим розширенням, яке вказане в налаштуваннях web-cepeepa як ознака сторінок з програмами на РНР. 70
повниться - змінні $PHP_AUTH_USER і SPHPAUTH PW у такому разі ще не будуть визначені.
Отже - видаємо вікно авторизації, для чого посилаємо браузеру відповідний заголовок:
Header("Www-authenticate: Basic
realm=\"защищенная зона"\"");
Браузер, отримавши таке, видасть відвідувачеві вікно (таке ж, як на мал. 8.1) із запитом логіна з паролем. Після натиснення кнопки Ok сторінка буде завантажена знов і в тому випадку, якщо логін і пароль відповідали вказаним в її тексті, виводитиметься останній її текст - той, що послідує за командою if, за її закриваючою фігурною дужкою. Ну а якщо логін і пароль будуть введений неправильно, то вікно авторизації вискочить знов - і у відвідувача з'явиться ще один шанс правильно авторизуватися. І так до тих пір, поки не будуть введений правильний логін і пароль.
Проте
у видаваному вікні є ще кнопка "Відміна"! і в тому випадку, якщо відвідувач натискуватиме її, то код просто почне виконуватися далі, з наступною після Header команди. Отже, в цей код і потрібно вставити ті команди, які повідомляють відвідувача, що так і не зумів ввести правильні логін з паролем, що він не може увійти до захищеної зони. (Не забудьте, що всі ці команди повинні знаходитися в межах адже блоку оператора if- нам треба, щоб вони виконалися лише в разі натиснення кнопки "Відміна"!).
Видамо
браузеру заголовок, що повідомляє про відмову в авторизації (вимагається деяким браузерам, а заразом і обнуляє змінні $PHP_AUTHJJSER і $PHP_AUTH_PW):
Header ("Http/1.0 401 Unauthorized");
...а потім - вкажемо той текст, який має бути виданий відвідувачеві в разі відмови в авторизації, - тобто натиснення ним кнопки "Відміна" в діалоговому вікні:
echo ("<р>доступ закритий!</р>");
(За бажання ви можете зробити цілу web-страницу, на якій детально розповісти, наприклад, як можна дістати правильні логін з паролем, і вставляти її текст сюди в разі відмови в авторизації за допомогою команди include: include ("noauth.php");
Наприклад, так варто зробити, якщо код цієї сторінки вельми великий або одна така сторінка використовуватиметься для декількох місць авторизації.)
І нарешті, завершимо роботу з поточною сторінкою - адже нам не потрібно виконувати той код, що далі; адже він має бути доступний лише авторизованим відвідувачам. Для виходу використовуваний комаду exit:
exit; }
Вона повністю припиняє як виведення web-страницы відвідувачеві, так і виконання якої-небудь коди. Ось, власне, і все:
?>
Для наочності - всі строчки коди разом:
<?php
if (($ Php_auth_user! = "log in") | | ($ Php_auth_pw! = "parol"))
{
Header("Www-authenticate: Basic realm=\"защищенная зона"\"");
Header("Http/1.0 401 Unauthorized");
...текст сторінки, видатної відвідувачеві в разі натиснення ним кнопки "Відміна"...
exit;
} ?>
Вказівка логіна і пароля в самому тексті PHP-сценария - простій, але не дуже зручний спосіб їх зберігання. Насправді - якщо ви плануєте надати доступ декільком відвідувачам, то вам доведеться давати їм одну і ту ж пару логіна і пароля. Це чревато тим, що при необхідності відмовити кому-небудь з них в доступі доведеться міняти пароль, про що доведеться повідомляти всі інші.
Нижче
приводиться невеликий код, що реалізовує перевірку вмісту авторизаційних змінних на збіг з якою-небудь парою "логін-пароль" із спеціального файлу паролів.
Допустимо,
файл, що містить логіни і паролі, розташовується в теці passw і називається passwr, а формат його простий - запис типа "логін пароль" (через пропуск) на кожній строчці (див. мал. 8.3). Для того, щоб цей файл не можна було завантажити через web-интерфейс, просто набравши його ім'я (і тим самим отримавши на екран весь його вміст), можете зробити це ім'я як можна довшим і хитромудрим (все одно воно фігурує лише в програмному коді, тобто з Мережі його взнати буде ніяк не можна), а можете просто заборонити читання даного файлу з Web, відповідно встановивши його атрибути, наприклад, в 770 (у CUTEFTP це робиться пунктом CHMOD з контекстного меню файлу, мал. 8.4).
Примітка:
Ще
заборонити читання вмісту директорій з Web можна, вказавши у файлі налаштувань web-сервера Apache (httpd, що іменується.conf) в розділі опису відповідного віртуального сервера параметр Location (наприклад:
<Location /passw>
deny from all
</location>
- у три рядки), проте доступ до файлу налаштувань web-сервера є не завжди.

Ріс.8.З. Простий файл паролів

Мал. 8.4. Щоб файл не "дістали" з Інтернету, встановите його параметри ось так...
Отже, почнемо сценарій. Командою file вважаємо файл відрядковий в масив...
Примітка:
Команда file поміщає в масив вказаний в її параметрі файл, поміщаючи кожен рядок файлу в окремий елемент масиву.
...і почнемо порівнювати пару "логін-пароль" кожної строчки файлу (тобто кожен елемент масиву) з тією парою, що ми отримали від користувача. Масив навіть немає нужди іменувати - досить просто вказати команду file в циклі обробки всіх елементів масиву f oreach (як згадувалося в гл. 3, цього оператора прочитує кожен елемент вказаного в його параметрах масиву в змінну з ім'ям, вказаним після ключового слова as, і виконує для кожного елементу масиву код, вказаний у фігурних дужках).
<?php
foreach (file("passw/passwr") as $k)
{
Коментар:
Оператор foreach працюватиме лише в РНР 4.0 і вище. Якщо ви можете використовувати лише РНРЗ, то замість цього оператора можна використовувати цикл for, вказавши в його параметрах величину масиву:
$b=file("passw/passwr");
for ($i = 1; $i < $sizeof($b); $i++)
{
Для зручності можна записати значення чергового елементу масиву в змінну:
$value=$k[$i];
Оскільки кожна строчка файлу завершувалася символом переведення рядка (вірніше, двома символами - з ASCII-кодами 10 і 13), то його необхідно видаляти перед порівнянням (у введених користувачем значеннях символу переведення рядка-то немає!) - це робить функція substr.
if (substr($k, 0 -2)=="$PHP_AUTH_USER $PHP_AUTH_PW") {
Примітка:
Команда substr
призначена
для виділення з рядка її частини. Рядок (або змінна, що її містить) має бути вказана в першому параметрі команди. Другий параметр - позиція, з якою починається частина (вірніше, число символів, які необхідно пропустити до початку виділення частині рядка), що виділяється, а третій -колічество символів, що виділяються.
Другий параметр може бути і негативним. В цьому випадку відлік позиції початку частини, що виділяється, йтиме не з початку, а з кінця рядки. Іншими словами, в результаті виконання команди substr ("qwertyuiop" -3, 2) з рядка "qwertyuiop" буде виділений рядок io - вона починається за 3 символи від кінця вихідного рядка і продовжується 2 символи.
Третій
параметр теж може бути негативним. В цьому випадку буде виділений рядок, що починається з вказаної в другому параметрі позиції і закінчується за стільки символів до кінця рядка, скільки вказано в третьому параметрі. Іншими словами, в результаті виконання команди substr ("qwertyuiop", 3 -2) з рядка "qwertyuiop" буде виділений рядок rtyui - вона починається після 3 символу вихідного рядка і закінчується за 2 символи до її закінчення.
В тому випадку, якщо параметри встановлені так, що виділити згодне їм символи з рядка виявляється неможливо (наприклад, другий параметр більший, ніж число її символів), то результатом роботи команди substr буде порожня строка- "".
Якщо у файлі з паролями була знайдена пара "логін-пароль", співпадаюча з даними, введеними користувачем, то привласнимо змінною $rez значення 1. Згодом нижче, коли нам треба буде перевірити, чи здійснилася авторизація, просто перевірятимемо значення цієї змінної - так простіше, ніж знов проводити перегляд файлу паролів.
$rez=l;
} }
Власне, і все - перевірка завершена. Тепер в тому випадку, якщо змінна $rez не рівна 1, слід видати вікно авторизації і отримати від відвідувача логін і пароль, а якщо рівна - те виводити сторінку далі.
if ($rez!=l) {
Header("Www-authenticate: Basic realm=\"защищенная зона"\"");
Header("Http/1.0 401 Unauthorized");
...текст сторінки, видатної відвідувачеві в разі натиснення ним кнопки "Відміна"...
exit;
} ?>
Як вже говорилося, змінні SPHPAUTHUSER і $PHP_AUTH_PW передаються всім сторінкам, які завантажуються в те ж саме вікно браузера, - тобто на яких відвідувач переходить. Тому їх можна використовувати для перевірки його прав на виконання тієї або іншої дії без нових запитів. Скажімо, якщо на якій-небудь сторінці, на яку відвідувач повинен перейти лише після авторизації, повинне вироблятися завантаження файлу, то перед завантаженням (у сценарії-обробнику завантаженого файлу, детальніше -см. гл. 7) слід знов перевірити відповідність переданих цій сторінці змінних SPHPAUTHJJSER і $PHP_AUTH_PW якій-небудь парі логіна і пароля у файлі паролів:
<?php
foreach (file("passw/passwr") as $k)
{
if (substr($k, 0 -2)=="$PHP_AUTH_USER $PHP_AUTH_PW")
{ ...команди завантаження файлу...
} } ?>
Даний код переглядає файл з паролями (так, знову той же файл...) і визначає, чи є там пара "логін-пароль", відповідна переданим сторінці змінним. Якщо є, то файл завантажується, якщо немає (тобто відвідувач зайшов на сторінку з формою для завантаження файлу, скажімо, по зробленій в "Вибраному" закладці або ввівши її URL в адресний рядок браузера, минувши сторінку авторизації), то завантаження не виробляється.
Іншими словами - один раз введені відвідувачем правильні логін з паролем записуються в змінні SPHPAUTHUSER і $PHP_AUTH_PW до тих пір, поки відвідувач не закриє вікно браузера (і всі вікна, відкриті по засланнях командою "Відкрити в новому вікні" з вікна, де сталася авторизація). На тих сторінках, куди відвідувач може попасти після авторизації, значення цих змінних можна перевіряти, порівнюючи з яким-небудь еталоном, наприклад, записаними в прихованому файлі логінами і паролями, і видавати відвідувачеві залежно від відповідності еталону його авторизаційних даних різну інформацію. Це запобіжить можливості попасти в "закриту зону" окрім вікна авторизації, через набір адреси в адресному рядку або по закладці.
Наприклад, для відправки на сторінку авторизації всіх, хто її не прошел, можна скористатися кодом
<?php
foreach (file("passw/passwr") as $k)
77
if (substr($k, 0 -2)=="$PHP_AUTH_USER $PHP_AUTH_PW")
{ $rez=l; } }
if ($rez!=l) {
Header ("Location: auth.php"); } ?>
де auth.php - сторінка з кодом видачі вікна авторизації. Заголовок Location, переданий браузеру, викликає його перехід на вказану в нім сторінку. Оскільки в даному коді використовується команда Header, то вона спрацює без помилок лише в тому випадку, якщо до неї в браузер відвідувача нічого не видавалося (окрім хіба що інших заголовків і cookies).
Особливості
описаного способу авторизації досить очевидні. Наприклад, дані авторизації зберігаються в змінних лише протягом одного сеансу роботи відвідувача; досить йому закрити вікно браузера, щоб необхідність введення логіна і пароля виникла знову. Для заповнення полий вікна авторизації не можна використовувати наявну в багато браузерах функцію автозаповнення форм (сучасні браузери можуть запам'ятовувати відповідність певному URL лише однієї пари "логін-пароль" і підставляти саме її в поля вікна), та і в інтерфейс сторінки це вікно вписати ніяк не можна (адже воно відображується браузером).
Проте є ще один прийом регламентації доступу до сторінок сайту - з використанням файлів cookies.
|