Nauka

Krótki kurs, aby zapoznać się z podstawami języka

Uwierzytelnianie HTTP w PHP

Rozdział 34. Uwierzytelnianie HTTP w PHP

Uwierzytelnianie HTTP jest obsługiwana przez PHP tylko wtedy, gdy PHP pracuje jako moduł Apache'a, nie jest dostępna w trybie CGI. W skrypcie można użyć funkcji header() by wysłać do przeglądarki komunikat "Wymagana autoryzacja", co spowoduje wyświetlenie okienka z polami Użytkownik i Hasło. Po wypełnieniu przez użytkownika tych pól, URL zawierający skrypt PHP zostanie ponownie wywołany z ustawionymi predefiniowanymi zmiennymi PHP_AUTH_USER, PHP_AUTH_PW i AUTH_TYPE zawierającymi odpowiednio nazwę użytkownika, hasło i typ autoryzacji. Zmienne te będą dostępne w tablicach $_SERVER oraz $HTTP_SERVER_VARS. Obecnie obsługiwane są autoryzacje typu "Basic" i "Digest" (od PHP 5.1.0). Więcej informacji znajdziesz w opisie funkcji header().

PHP Version Note: Zmienne superglobalne, takie jak $_SERVER, udostępniono w PHP 4.1.0. $HTTP_SERVER_VARS są dostępne od PHP 3.

Przykładowy skrypt wymuszający autoryzację klienta:

Przykład 34-1. Uwierzytelnianie Basic HTTP

<?php
  
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    
header('WWW-Authenticate: Basic realm="My Realm"');
    
header('HTTP/1.0 401 Unauthorized');
    echo
'Tekst do wysłania, jeśli użytkownik wciśnie przycisk Anuluj';
    exit;
  } else {
    echo
"<p>Hej {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo
"<p>Twoje hasło to {$_SERVER['PHP_AUTH_PW']}.</p>";
  }
?>

Przykład 34-2. Przykład uwierzytelnianie Digest HTTP

Ten przykład pokazuje jak zaimplementować proste umierzytelnianie Digest HTTP. Po więcej informacji przeczytaj RFC 2617.

<?php
$realm
= 'Zastrzeżona strefa';

//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(
'Tekst do wysłania kiedy użytkownik kliknie klawisz anuluj');
}


// analiza zmiennej PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset(
$users[$data['username']]))
    die(
'Nieprawidłowe listy uwierzytelniające!');


// tworzenie prawidłowej odpowiedzi
$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(
'Nieprawidłowe listy uwierzytelniające!');

// ok, prawidłowa nazwa użytkownika i hasło
echo 'Jesteś zalogowany jako: ' . $data['username'];


// function to parse the http auth header
function http_digest_parse($txt)
{
    
// zabezpieczenie przeciwko brakującym informacjom
    
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    
$data = array();

    
preg_match_all('@(\w+)=([\'"]?)([a-zA-Z0-9=./\_-]+)\2@', $txt, $matches, PREG_SET_ORDER);

    foreach (
$matches as $m) {
        
$data[$m[1]] = $m[3];
        unset(
$needed_parts[$m[1]]);
    }

    return
$needed_parts ? false : $data;
}
?>

Kompatybilność: Należy uważać z linijkami dodawanymi do nagłówka HTTP. W celu zachowania maksymalnej zgodności ze wszystkimi klientami, słowo Basic powinno zaczynać się dużą literą "B", wartość realm powinna być otoczona cudzysłowami (nie apostrofami), i dokładnie jeden znak odstępu powinien poprzedzać kod 401 w linii HTTP/1.0 401. Parametry autoryzacyjne muszą być oddzielone przecinkami jak pokazano to w przykładzie digest powyżej.

Zamiast wyświetlać wartość PHP_AUTH_USER i PHP_AUTH_PW, jak to zrobiono w powyższym przykładzie, zechcesz zapewne sprawdzić poprawność nazwy użytkownika i hasła. Na przykład poprzez zapytanie do bazy danych lub odnalezienie użytkownika w pliku dbm.

Należy uważać na kapryśne przeglądarki Internet Explorer. Są wrażliwe na kolejność wysyłanych nagłówków HTTP. Wysłanie nagłowka WWW-Authenticate przed HTTP/1.0 401 powinno rozwiązać problem.

Aby zapobiec sytuacji w której ktoś napisze skrypt wykradający hasło wysłane tradycyjnym zewnętrznym mechanizmem, zmienne PHP_AUTH nie będą ustawiane, jeśli dla danej strony aktywna jest autoryzacja zewnętrzna i tryb bezpieczny jest włączony. Bez względu na to, REMOTE_USER może zostać użyte do zidentyfikowania użytkownika autoryzowanego zewnętrznie Zatem, możesz użyć $_SERVER['REMOTE_USER'].

Konfiguracja: Aby wykryć czy miała miejsce zewnętrzna autoryzacja, PHP sprwadza obecność dyrektywy AuthType.

Powyższa metoda nie zapobiega jednak wykradaniu haseł do stron wymagających autoryzacji przez kogoś, kto na tym samym serwerze kontroluje strony nie wymagające autoryzacji.

Zarówno Netscape Navigator jak i Internet Explorer opróżnią bufor autoryzacji po otrzymaniu od serwera kodu 401. Można w ten sposób wylogowanić użytkownika i zmusić go do ponownego wysłania nazwy użytkownika i hasła. Tej metody można użyć do wylogowania użytkownika po określonym czasie lub stworzenia przycisku "Wyloguj".

Przykład 34-3. Uwierzytelnianie HTTP z wymuszeniem przelogowania

<?php
  
function authenticate() {
    
header('WWW-Authenticate: Basic realm="Testowy system autoryzacji"');
    
header('HTTP/1.0 401 Unauthorized');
    echo
"Musisz podać poprawny login i hasło by wejść na tę stronę\n";
    exit;
  }

  if (!isset(
$_SERVER['PHP_AUTH_USER']) ||
    (
$_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    
authenticate();
  } else {
    echo
"<p>Witaj: {$_SERVER['PHP_AUTH_USER']}<br />";
    echo
"Poprzednio: {$_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='Re Authenticate' />\n";
    echo
"</form></p>\n";
}
?>

Powyższa metoda nie jest wymagana przez autoryzację HTTP typu "Basic", więc nie można na niej polegać. Testy z przeglądarką Lynx pokazały, że Lynx nie usuwa danych o autoryzacji po odebraniu od serwera kodu 401, zatem przejście wstecz a następnie do przodu otworzy stronę, chyba, że wymagania co do danych autoryzacji zmieniły się. Użytkownik może jednak użyć klawisza '_' by usunąc dane o autoryzacji.

Zwóć uwagę, że do wersji PHP 4.3.3, Autoryzacja HTTP nie działała na serwerze Microsoft IIS z PHP w wersji CGI z powodu ograniczeń IIS. Aby zmusić go do działania w PHP 4.3.3+ musisz wyedytować "Bezpieczeństwo katalogów" w konfiguracji IIS. Kliknij na "Edytuj" i zaznacz wyłącznie "Anonimowy Dostęp", wszystkie inne pola powinny pozostać nie zaznaczone.

Inne ogranicznie jest jeśli używasz modułu IIS (ISAPI) i PHP 4, nie możesz wtedy użyć zmiennych PHP_AUTH_* ale zamiast nich, dostępna jest zmienna HTTP_AUTHORIZATION. Na przykład rozważ następujący kod: list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

Notatka IIS:: Aby Autoryzacja HTTP działała z IIS, dyrektywa PHP cgi.rfc2616_headers musi być ustawiona na 0 (domyślna wartość).

Notatka: Jeśli włączony jest tryb bezpieczny, uid skryptu jest doklejany do pola realm nagłówka WWW-Authenticate.


mario download

Posty z forum

Ostatnie wiadomości z grupy dyskusyjnej

problem z komputrem
Proponuje sciagnac u kolegi i wypalic na plycie obraz z programem antywirusowym, np. Kaspersky Rescue Disk...
Router TL-R402M-problem
Router nie powinien powodowac takich rzeczy. Jestes pewny, ze to nie wina serwerow skad pobierasz dane ? Czy jest tak w konkretnym programie, np. do...
"We pay for your Mio" - dajcie znać
Jesli ktos zaryzykował i kupił nawigacje Mio i zamiast gwarantowanych 10 Euro postanowił zagrać o 100 niech da znac jeśli wygra. Ciekawi mnie jak to...
poradzcie mezczyzni jaka nawigacje kupic:)
Ja tez nie mogę wziąc udziału bo już mam jednego takiego....:( Ale pomysł fajny. Kumpel mówił, że ta gierka jak się gra o 100 Euro jest nieźle...
problem z kamerą internetową
witam. mam ten sam problem z kamerka i sys Vista. Jezeli jest ktos zyczliwym na tym forum to prosze o przeslanie sterownikow do visty na mojego...

Mam problem. Otóż: pole na tekst to grafika. Chcę aby to jaśniejsze pole było czymś w rodzaju nie wiem... ramki, pływającej ramki. Po prostu, żebym mógł tam pisać, żeby było to tło (jaśniejsze pole), oraz aby się mogło przewijać.