Potřebujete zpřístupnit soubory pouze uživatelům přihlášeným k serveru pod svým jménem a heslem? K tomu můžete použít autorizaci HTTP serveru. Pokud ale nechcete, aby se pro každý soubor zobrazoval nehezký dialog, a přitom chcete mít soubory dobře chráněné, nabízím jiné řešení.

Problém

HTTP autorizace umožňuje pro celé adresáře (nikoli pro jednotlivé soubory) nastavit jména a hesla uživatelů, kteří budou mít k souborům přístup. Při požadavku na přístup se uživateli v prohlížeči zobrazí dialogový box pro zadání jména a hesla. Tento dialogový box však není nijak uživatelsky modifikovatelný a je graficky dost jednoduchý. Hodí se tedy tam, kde se jedná pouze o zabezpečení dat, a nezáleží na designu serveru. Dobře graficky vypadajícímu serveru takový šedý dialog snižuje image.

Kdybychom dali odkaz na soubory pouze řádně přihlášeným uživatelům, zabezpečujeme tím pouze odkaz na soubor, nikoli samotný soubor, a kdyby někdo zjistil jméno chráněného souboru, nic už by mu nebránilo v přístupu.

Řešení

Jak tedy umožnit uživateli stáhnout soubory a přitom je dostatečně chránit? Vysvětlím způsob, který umožní zpřístupnit soubory pouze přihlášeným uživatelům a přitom nebude využívat autorizaci HTTP serveru. Přitom předpokládám, že samotná autorizace uživatele na stránkách je již zajištěna. Tu lze řešit různými způsoby, jeden z nich je popsán v článku ”Autorizace uživatelů v PHP”, jiným způsobem je využití sessions.

Soubory, které chcete zabezpečit před neoprávněným přístupem, uložte do svého adresáře, ale mimo adresový prostor webu (mimo adresář httpd). To může být problém u některých freehostingů, neboť tam často bývá váš celý adresář namapován na adresový prostor webu. Pak je třeba přístup do některých větví zakázat pomocí souboru .htaccess. Tím je zajištěno, že soubory nemají žádnou adresu na webu a nikdo k nim nemůže přistoupit přímo. Budu předpokládat, že jsou soubory uložené v adresáři c:\data\tajne, v UNIXu by to mohlo být třeba /home/ja/tajne.

Pro zpřístupnění souboru uživateli vytvoříme skript, který kýžená data načte ze souboru – PHP má přístup k vašim lokálním souborům (záleží však na konkrétním nastavení PHP) – a takto načtená data vypíše na standardní výstup. Pozor! Na standardní výstup jsme zapsali pouze data souboru, ale nic o jeho jménu a typu. Aby prohlížeč správně pochopil význam dat, je třeba ještě před začátkem vypisování dat vypsat http hlavičku. Do hlavičky jednak uvedeme jméno souboru pomocí direktivy Content-disposition. Dále do hlavičky nastavíme MIME typ pomocí direktivy Content-type type na hodnotu "application/force-download". Tím říkáme, že se jedná o řetězec bytů a že se má tento soubor uložit. Kdybychom Content-type neuvedli, některé typy souborů, např. obrázky a textové soubory (podle nastavení našeho prohlížeče), by se neukládaly, ale zobrazily by se v okně prohlížeče.

Kromě těchto dat nesmí skript pro výpis souboru vypisovat žádné další informace, tedy ani standardní HTML tagy HTML, HEAD, BODY apod.

Popis skriptu

Tento skript si pojmenujeme pristup.php. Má jeden parametr soubor udávající jméno zpřístupňovaného souboru. Na úvod se zkontroluje, zda se opravdu jedná o daného uživatele a zda má přidělena práva na získání souboru, který žádá. To se ověřuje, jak již bylo řečeno, buď pomocí sessions nebo nějakým jiným způsobem. Na začátku skriptu je nastavená proměnná cesta udávající adresář, ve kterém jsou zpřístupňované soubory. Pomocí funkce header() vypíšeme HTTP hlavičku, do níž vypíšeme Content-disposition a Content-type.

Samotná data vypíšeme pomocí funkce readfile(), která čte data ze souboru a vypisuje je na standardní výstup.

Tady je skript pristup.php:

<?
$cesta = „c:\\data\\tajne\\“;
// $cesta = „/home/ja/tajne/“;
function autentifikace_v_poradku() { return true; }
// tady provedete autorizaci uživatele tak, jak to děláte i na ostatních stránkách
if (!autorizace_v_poradku()) {
    header(„HTTP/1.0 Error 401 You are not authorized to perform this operation“);
    exit;
    }
// v případě chyby při autorizaci se vyvolá chyba HTTP serveru 401 – "neautorizovaný přístup"
header(”Content-disposition: filename=$soubor”);
header(”Content-type: application/force-download”);
// vypsání HTTP hlavičky
readfile($cesta.$soubor, ”r”);
// vypsání obsahu souboru
?>

Volání skriptu

Odkaz na požadovaný dokument pak znamená klasický odkaz na daný skript.

<a href="pristup.php?soubor=tajne.txt">DOKUMENT – text</a>
<a href="pristup.php?soubor=tajne.gif">DOKUMENT – gif</a>
<a href="pristup.php?soubor=tajne.xls">DOKUMENT – xls</a>
<a href="pristup.php?soubor=tajne.pdf">DOKUMENT – pdf</a>

Dodatky

Při praktickém použití dobře prověřte předávané jméno souboru. Pokud byste tak neučinili, mohl by se všetečný uživatel snadno dostat i k souborům, které jste neměli v úmyslu publikovat, a jejichž publikování by vás mohlo v konečném důsledku mrzet :-). Doporučoval bych přímo vložit podmínku typu…

if ($soubor==“soubor1″ || $soubor==“soubor2″ || …) …

…popřípadě neudávat jména souborů vůbec a místo nich dávat pouze čísla souborů, která následně na jména převedete ve skriptu.

Rovněž si dejte pozor, že ne všem uživatelům chcete zpřístupnit stejné skupiny souborů, a tudíž by bylo vhodné kombinovat kontrolu jména souboru s autorizací uživatele.

Hodně štěstí.

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