Forum und email

PHP ja HTTP-autentikaatio

PHP:n HTTP-autentikaatiotuki on käytettävissä ainoastaan mikäli PHP on asennettu Apachen moduuliksi, eikä siten ole saatavilla CGI-moduulissa. Apachen moduulina ajettavassa PHP-skriptissä voidaan header() -funktiolla lähettää Web-selaimelle autentikaatiopyyntö, jolloin toteutustavasta riippuen selain kysyy käyttäjältä käyttäjätunnusta ja salasanaa. Kun käyttäjä on saanut syötettyä nämä tiedot, URL:ia, jossa tämä skripti sijaitsee, kutsutaan uudelleen. Tällä kertaa ennalta määriteltyjen muuttujien PHP_AUTH_USER, PHP_AUTH_PW ja AUTH_TYPE arvoina on käyttäjän syöttämät tiedot sekä autentikaatiotyyppi. Nämä muuttujat löytyvät $_SERVER ja $HTTP_SERVER_VARS -listoista. Vain yksinkertainen (Basic) autentikaatio on tuettu. Lisätietoja asiasta löytyy funktiosta header().

Note: PHP:n versioista Superglobaalit, kuten $_SERVER tulivat käyttöön PHP:n versiossa » 4.1.0. $HTTP_SERVER_VARS on ollut käytössä PHP 3:sta lähtien.

Seuraavanlaisella skriptinpätkällä voidaan pakottaa asiakas tunnistautumaan sivulle.

Example#1 HTTP-autentikaatioesimerkki

<?php
  
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    
header('WWW-Authenticate: Basic realm="Suojattu alue"');
    
header('HTTP/1.0 401 Unauthorized');
    echo 
'Tämä teksti näytetään käyttäjälle mikäli hän hylkää ' .
     
'autentikaatiopyynnön.';
    exit;
  } else {
    echo 
"<p>Päivää, {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo 
"<p>Syötit salasanan {$_SERVER['PHP_AUTH_PW']}.</p>";
  }
?>

Note: Huomautus yhteensopivuudesta Muista kiinnittää huomiota HTTP-otsikkotietojen kirjoitusasuun! Taataksesi mahdollisimman hyvän yhteensopivuuden eri selainten kanssa, huomaa että avainsana "Basic" tulee kirjoittaa isolla alkukirjaimella "B", realm-attribuutin arvon tulee olla lainausmerkeissä (ei heittomerkein eroteltuna) ja otsikkorivin HTTP/1.0 401 koodinumeroa 401 ennen tulee olla tasan yksi välilyönti.

Pelkän syötettyjen arvojen tulostamisen sijaan voit mahdollisesti haluta tarkistaa muuttujien PHP_AUTH_USER ja PHP_AUTH_PW sisällön oikeellisuuden, ehkäpä tekemällä kyselyn tietokantaan tai etsimällä käyttäjää dbm-tiedostosta.

Varo virheellisesti toimivia Internet Explorerin versioita. Ne saattavat olla erittäin tarkkoja siitä missä järjestyksessä HTTP-otsikkotiedot syötetään. WWW-Authenticate -otsikon lähettäminen ennen HTTP/1.0 401 -otsikkoa näyttäisi kuitenkin toimivan tällä hetkellä.

PHP 4.3.0 ja uudemmat versiot eivät aseta PHP_AUTH-muuttujia, mikäli ulkoinen autentikaatio on otettu käyttöön määritetyllä sivulla ja mikäli safe mode on käytössä. Tämä estää sellaisten skriptien teon, joilla voitaisiin paljastaa perinteisin metodein autentikoidun käyttäjän tunnukset. Siitä huolimatta, REMOTE_USER -muuttujaa (eli $_SERVER['REMOTE_USER']) voidaan käyttää ulkoisesti autentikoidun käyttäjän tunnistamiseen.

Note: Huomaa konfiguroidessa PHP määrittää asetuksen AuthType olemassaolon perusteella sen, onko ulkoinen autentikaatio käytössä.

Huomaa kuitenkin, että edellämainittu tapa ei estä samalla palvelimella sijaitsevia ei-autentikoituja URLeja varastamasta autentikoidun URLin salasanoja.

Sekä Netscape Navigator että Internet Explorer tyhjentävät HTTP-autentikaatiotiedot välimuististaan saadessaan HTTP-vastauksen 401. Tällä keinolla voidaan "kirjata ulos" käyttäjä, pakottaen heidät syöttämään käyttäjätunnuksensa uudelleen. Jotkut käyttävät tätä keinoa istuntojen aikakatkaisuun tai "kirjaudu ulos" -painikkeen toteuttamiseen.

Example#2 Esimerkki uudelleenautentikoitumisen pakottamisesta

<?php
  
function authenticate() {
    
header('WWW-Authenticate: Basic realm="Testijärjestelmä"');
    
header('HTTP/1.0 401 Unauthorized');
    echo 
"Syötä käyttäjätunnus ja salasana käyttääksesi tätä resurssia.\n";
    exit;
  }

  if (!isset(
$_SERVER['PHP_AUTH_USER']) ||
      (
$_POST['SeenBefore'] == && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
   
authenticate();
  }
  else {
   echo 
"<p>Tervetuloa: {$_SERVER['PHP_AUTH_USER']}<br />";
   echo 
"Vanha: {$_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='Vaihda käyttäjää' />\n";
   echo 
"</form></p>\n";
  }
?>

Tämänkaltaista toiminnallisuutta ei kuitenkaan vaadita HTTP Basic authentication -standardissa, joten siihen ei tulisi koskaan luottaa. Testaaminen Lynx-selaimella osoittaa, että Lynx ei tyhjennä autentikaatiotietojaan saadessaan palvelimelta vastauksen 401, joten palaaminen edelliselle sivulle ja samantien takaisin avaa uudelleen saman resurssin -- niin kauan kuin käyttöoikeusvaatimukset eivät ole muuttuneet. Käyttäjä voi kuitenkin painaa Lynxissä '_' -näppäintä tyhjentääkseen autentikaatiotiedot.

Huomaa myös, että HTTP-autentikaatio ei ole toiminut ennen PHP:n versiota 4.3.3 CGI-moduulina Microsoftin IIS-palvelimessa sen rajoittuneisuuden takia. Sen käyttöönotto PHP 4.3.3:ssa tai uudemmissa versioissa vaatii asetuksen "Directory Security" muokkausta. Klikkaa kohtaa "Edit" ja valitse ainoastaan "Anonymous Access", kaikki muut kentät tulee jättää tyhjäksi.

PHP:n IIS-moduulissa (ISAPI) on puolestaan sellainen puute, että PHP_AUTH_* muuttujia ei voida käyttää, vaan niiden sijaan on käytettävä muuttujaa HTTP_AUTHORIZATION. Kokeile esimerkiksi seuraavaa koodia: list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));.

Note: Huomautus IIS:n käyttäjille Jotta HTTP-autentikaatio toimisi IIS-palvelimen kanssa, cgi.rfc2616_headers-asetuksen arvon tulee olla 0, joka on myös asetuksen oletusarvo.

Note: Mikäli safe mode on käytössä, ajettavan skriptin UID lisätään WWW-Authenticate-otsikon realm-attribuutin arvoon.