Pokud se přihlásíme k aplikaci pomocí standardní HTTP autentizace, prohlížeč si jednou zadané údaje (ať už do URL nebo do přihlašovacího dialogu) zapamatuje a při každém volání nějaké stránky z téhož serveru předává aplikaci jméno a heslo. Zkusme se podívat, jak lze prohlížeč přesvědčit, aby „zapomněl“.

Díky v úvodu zmíněné nevýhodě a také díky tomu, že jméno a heslo (byť zakódováno do BASE64) je předáváno po síti s každou volanou stránkou, není HTTP autentizace příliš oblíbená. Pro snadnost použití však může být ideální pro prostředí intranetu nebo pro jednodušší aplikace, kde nepotřebujeme robustní zabezpečení.

Jedním ze způsobů, jak nedostatky HTTP autentizace napravit, je využití JavaScriptu, pomocí něhož k odhlášení nabídneme zavření okna, čímž vlastně dojde k zapomenutí přihlašovacích údajů. Vyvstává zde ovšem problém s okny, která byla otevřena i se zděděným prostředím mateřského okna v okamžiku, kdy v něm byl přihlášen uživatel. Všechna další takto otevřená okna si přihlašovací údaje pamatují a lze v nich tedy pracovat s aplikací, i když se uživatel „odhlásil“ (zavřel mateřské okno). Toto je velký nedostatek, který může uživatele zmást, ale také může znemožnit přihlášení jinému uživateli. Například pokud se v jednom okně přihlásí a potom si pomocí CTRL+N otevře nové okno. V tomto novém okně pak bude stále přihlášen, i když už původní okno zavřel. Zázračný lék neexistuje, musíme prostě uživatele přimět k tomu, aby pozavíral všechna okna a vstupoval tak do aplikace s „čistým štítem“.

Před zavřením okna (tedy před odhlášením) uložíme cookie, které informuje, že došlo k odhlášení. Platnost této cookie nastavíme tak, aby vypršela v okamžiku zavření okna prohlížeče. V naší aplikaci potom vždy testujeme, zda není nastavená tato odhlašovací cookie a pokud je, odepřeme k aplikaci přístup, doporučíme uživateli zavřít okno prohlížeče a otevřít nové (toto nelze provést automaticky ze skriptu).

Vzhledem k předpokládanému nasazení spíše v intranetu využijeme pro ukládání cookie JavaScriptu. Efektním doplňkem pro Internet Explorer je při odhlašování přepnout zobrazení do černobílého režimu, jak je známé z Windows XP.

Při použití prohlížeče Internet Explorer můžeme určitým trikem vytvořit plnohodnotně funkční odhlášení. Ani IE neumí „zapomenout“ údaje přihlášeného uživatele, ale narozdíl od jiných prohlížečů, umí použít nové údaje. Tyto nové údaje mu vnutíme v URL – použijeme jméno neexistujícího uživatele, takže přihlášení selže a objeví se přihlašovací dialog, ve kterém se může přihlásit nový uživatel. Protože toto jméno se objeví jako přednastavené v přihlašovacím dialogu, použijeme jméno, které bude vypadat jako nápověda, čímž tento nedostatek zamaskujeme. Podívejte se na ukázku: jméno je interval, heslo isthebest.

Jméno neexistujícího uživatele, které zadáváme do URL pro odhlášení/přihlášení jiného uživatele, musíme zadat bez diakritiky, nebo zakódované pomocí speciálních znaků pro URL (v PHP jej získáme funkcí urlencode()). Zde je uveden „nový uživatel“ a heslo „XXX“:

http://nov%FD%20u%9Eivatel:XXX@server.cz/aplikace.php

Jakmile proběhne korektní přihlášení, je ještě potřeba dostat přihlašovací údaje pryč z URL. Toho dosáhneme tak, že si při volání funkce pro odhlášení nastavíme určitý parametr a v části, kde se ověří platné přihlášení nového uživatele, pak v případě nastavení tohoto parametru přesměrujeme na tentýž skript, ovšem bez jména a hesla v adrese. Pokud by totiž jméno a heslo zůstalo v adrese, nebylo by možno stránkami procházet, uživatel by byl stále odhlašován. Kvůli problému s uživatelským jménem a heslem doplněným do URL, musíme také odkazy na nové přihlášení, které se zobrazí v případě, že se přihlášení nezdařilo, udávat s absolutní cestou tak, aby URL pak byla bez přihlašovacích údajů. I tuto funkci můžeme okořenit přepnutím na černobílé zobrazení při kliknutí na odkaz.

Nejprve si popíšeme skript login.php, který zajišťuje všechny funkce ověření přihlášení:

<?php
if ($_COOKIE[‚loggedout‘]==1) // test odhlašovací cookie
{
  echo ‚Z aplikace jste se již odhlásili.<br />‘;
  echo ‚<a href=“javascript: self.close()“>Zavřete toto okno</a> a otevřete aplikaci v novém okně prohlížeče.‘;
  exit;  // tento exit je vhodné nahradit tak, aby výsledná stránka byla korektním HTML dokumentem
}
else
{
  $path=SubStr($_SERVER[‚SCRIPT_NAME‘], 0, StrRPos($_SERVER[‚SCRIPT_NAME‘],’/‘));
  $path.=“/index.php“; // „čistá“ cesta k index.php do odkazů pro přihlášení k aplikaci
  If (!IsSet($_SERVER[‚PHP_AUTH_USER‘])) // pokud uživatel právě přišel, zobrazíme formulář
  {
    Header($_SERVER[‚SERVER_PROTOCOL‘].‘ 401 Unauthorized‘);
    Header(‚WWW-Authenticate: Basic realm=“Test odhlašování“‚);
    echo ‚Bez hesla to nepůjde…<br />‘; // když nic nevyplní, vypíšeme chybové hlášení
    echo ‚<a href=“http://‘.$_SERVER[‚HTTP_HOST‘].$path.'“>Přihlásit</a>‘;
    Exit;  // tento exit je vhodné nahradit tak, aby výsledná stránka byla korektním HTML dokumentem
  }
  elseif (!($_SERVER[‚PHP_AUTH_PW‘] == ‚isthebest‘ && StrToLower($_SERVER[‚PHP_AUTH_USER‘]) == ‚interval‘))
  { // uživatel byl ověřen, přihlášení není platné
    Header($_SERVER[‚SERVER_PROTOCOL‘].‘ 401 Unauthorized‘);
    Header(‚WWW-Authenticate: Basic realm=“Test odhlašování“‚);
    echo ‚Neautorizovaný přístup<br />‘;
    echo ‚<a href=“http://‘.$_SERVER[‚HTTP_HOST‘].$path.'“>Přihlásit</a>‘;
    Exit;  // tento exit je vhodné nahradit tak, aby výsledná stránka byla korektním HTML dokumenterm
  }
  if ($_GET[‚logout‘]==1) // podpora přihlášení jiného uživatele v IE
 { // přesměrovat na stejnou adresu, ale bez přihlašovacích údajů v adrese
    Header(‚Location:http://‘.$_SERVER[‚HTTP_HOST‘].$_SERVER[‚SCRIPT_NAME‘]);
    Exit;
  }
} // přihlášení uživatele je platné, aplikace může pokračovat
?>

V tomto ukázkovém skriptu jsou v případě odepření přístupu k aplikaci použity funkce Exit pro ukončení provádění skriptu. Ty je pak nutné ve skutečné aplikaci nahradit, například vložením souboru s chybovým hlášením, nebo nastavit jméno souboru, který bude vkládat hlavní skript aplikace. Ověření jména a hesla uživatele je také jen ukázkové, pro jednoduchou ochranu může postačit sepsat několik uživatelů přímo do zdrojového kódu, obvykle však použijeme ověření dotazem do databáze.

Do hlavního skriptu pak přidáme obslužný JavaScript pro odhlašování a ukládání cookie a odkaz na odhlášení. V podmíněném komentáři uvedeme odkaz na přihlášení jiného uživatele, který se objeví pouze v IE, v ostatních prohlížečích by stejně nebyl funkční.

<?php
require (‚login.php‘); // zavedení skriptu ověřujícího oprávnění uživatele
?>
<html>
<head>
<meta http-equiv=“Cache-control“ content=“no-cache“>
<meta http-equiv=“Pragma“ content=“no-cache“>
<meta http-equiv=“expires“ content=“0″>
<meta http-equiv=“Content-Type“ content=“text/html; charset=windows-1250″>
<title>Odhlašování HTTP Autentifikace</title>
</head>
<body bgcolor=“#5a8ac6″>
<script language=“JavaScript“ type=“text/javascript“ src=“cookies.js“></script>
<script language=“JavaScript“ type=“text/javascript“>
<!–
function logout()
{
  if (navigator.appName==’Microsoft Internet Explorer‘)
    document.body.style.filter=’gray(enabled=1)‘; // přepnout na černobílé
  logoutyes=confirm(‚Chcete se odhlásit?‘) // zobrazit výzvu
  if (logoutyes)
  { // uživatel potvrdil souhlas s odhlášením
    MyCookie.Write(‚loggedout‘,1); // nastavit odhlašovací cookie
    if (navigator.appName==’Microsoft Internet Explorer‘) // trik v IE, nezobrazí dotaz před zavřením okna
      top.opener=“interval“;
    top.window.close(); // zavřít okno
}
else // uživatel nesouhlasil s odhlášením
  if (navigator.appName==’Microsoft Internet Explorer‘)
    document.body.style.filter=’gray(enabled=0)‘; // vrátit barevné zobrazení
}
// –>
</script>

Nějaký text a kód stránky

<p>
<br /><a href=“javascript: logout()“>Odhlásit se</a> // odhlášení funkcí logout v Javascriptu
<!–[if IE]>
<br /><a href=“http://nov%FD%20u%9Eivatel:XXX@<?php echo $_SERVER[‚HTTP_HOST‘].$_SERVER[‚SCRIPT_NAME‘] ?>?logout=1″ onClick=“document.body.style.filter=’gray(enabled=1)'“>Jiný uživatel</a> // odkaz na přihlášení jiného uživatel v IE
<![endif]–>
</p>
</body>
</html>

Odkaz na přihlášení nového uživatele v IE obsahuje zakódované jméno uživatele a adresu, která je generována pomocí PHP tak, aby aplikace byla lehce přenositelná na libovolný server a do libovolného adresáře.

Uvedený trik je samozřejmě možné použít po úpravě syntaxe také v ASP, samotné hlídání odhlášení pomocí cookies je možné přenechat kompletně JavaScriptu. Pokud vás článek zaujal, můžete si zdrojové kódy ukázky stáhnout.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět