Pokud chceme některé soubory ke stažení zpřístupnit jen vybraným uživatelům, je vhodné je učinit přímo přes web nepřístupné (v Apache např. umístěním mimo DocumentRoot nebo do adresáře s omezeným přístupem). Pokud to neuděláme, vystavujeme se riziku, že cestu k souboru uživatel uhodne nebo jinak zjistí a stáhne si soubor bez ověření. Po ověření práv je tedy nejlepší soubor uživateli poslat přímo PHP skriptem. Tomu se nevyhneme ani v případě, kdy je soubor uložen v databázi a přímá cesta k němu neexistuje.
Aby prohlížeč věděl, co si se souborem má počít, musíme ho samozřejmě poslat se správným Content-Type. Pokud soubor chceme navíc poslat pod správným názvem, už to tak jednoduché bohužel není. Hlavička Content-Disposition, pomocí které se název souboru dá předat, je sice široce implementovaná, v HTTP ale přímo není a některé proxy ji opravdu ignorují. Pokud tedy nechceme uživateli např. spustitelný soubor posílat pod názvem stahnout.php
, nelze se na tuto hlavičku spolehnout.
<?php // zde ověřit, jestli má uživatel k souboru $_GET["filename"] právo header("Content-Type: application/octet-stream"); // při stažení přes některé proxy servery se název souboru nepředá header("Content-Disposition: attachment; filename=\"$_GET[filename]\""); readfile("data/$_GET[filename]"); ?>
Řešit se to dá tak, že název souboru uvedeme jako poslední část URL. V Apache je možné zapnout direktivu AcceptPathInfo a použít cestu stahnout.php/aplikace.exe
.
<?php $filename = substr($_SERVER["PHP_SELF"], strlen($_SERVER["SCRIPT_NAME"]) + 1); // zde ověřit, jestli má uživatel k souboru $filename právo header("Content-Type: application/octet-stream"); readfile("data/$filename"); ?>
Tento problém lze pochopitelně řešit i pomocí mod_rewrite například pravidlem RewriteRule ^/data/(.*) /stahnout.php?filename=$1
.
Diskuse je zrušena z důvodu spamu.