Pravděpodobně na podobný problém jako já narazil skoro každý, kdo programuje třeba elektronický obchod – potřeba zobrazit pdf soubory pouze autorizovaným uživatelům.

Příkladem mohou být vygenerované faktury – chcete je mít uložené na serveru, chcete je zobrazovat, ale rozhodně je nechcete zpřístupnit komukoli, kdo odhadne název souboru.

Celé řešení není složité, jediné, na čem jsem se trochu zasekl a co mě trochu překvapilo je, že třída FileResponse vždy soubor nabídne ke stažení a zobrazit pdf soubory přímo v prohlížeči není možné. Pokud chcete vidět, jak jsem se vypořádal pouze s tímto problémem, podívejte se na konec tohoto článku nebo rovnou na mou PdfResponse na githubu.

Tip č. 1: podívejte se, jak jsem problém řešil na anglickém Nette fóru.

Tip č. 2: pokud čemukoli nerozumíte, napište mi to do komentářů, pokusím se poradit!

Tip č. 3: dělám to špatně? Nebo to není úplně špatně, jen to jde prostě dělat líp? Podělte se o Vaše zkušenosti, já i další čtenáři Vám budeme vděční! Díky.

Jdeme na to!

Moje řešení se skládá z následujících částí:

  1. správná routa
  2. presenter, který bude ověřovat autorizaci (přihlášený uživatel, dostatečná práva)
  3. adresář s pdf soubory, který bude pomocí .htaccess souboru zabezpečený proti volnému prohlížení
  4. něco, co bude pdf dokumenty v prohlížeči zobrazovat

1. Routa

Routu doplníme do souboru RouterFactory.php, případně do souboru bootstrap.php – podle toho, kde routy nastavujete. V Nette Sandboxu ve verzi 2.0.10 jsou routy nastaveny v app/router/RouterFactory.php.

$router[] = new Route('faktura/<filename>', 'Restricted:invoice');

Tip: nevíte si rady s routami? Podívejte se do dokumentace.

2. Presenter

Tip: nejste si jistí, jak má presenter vypadat? Podívejte se do dokumentace.

Takhle vypadá můj RestrictedPresenter.php, na který odkazuju v routě:

<?php
class RestrictedPresenter
{
    public function startup()
    {
        /* pokud měníte metodu startup, nezapomeňte zavolat jejího předka */
        parent::startup();

        /* ověření autorizovaného přístupu */
        if(!$this->auth->isAdministrator()) {
            $this->error('Nemáte oprávnění pro přístup na tuto stránku.', 403);
        }
    }

    /**
     * akce, ktera zobrazi pdf soubor
     */
    public function actionInvoice($filename)
    {
        // RESTRICTED_DIR je neco jako APP_DIR, mam ho definovany v index.php
        // PdfResponse je moje trida, ktera vychazi z puvodni FileResponse
        $this->sendResponse(new HoLi\PdfResponse(
            RESTRICTED_DIR . '/invoices/' . $filename,
            $filename, 'application/pdf'));
    }
}

3. Adresář s pdf soubory

V adresáři www mám podadresář, který se jmenu _restricted (to není zásadní, pojmenovat si ho můžete, jak chcete). Důležité je, abyste do něj umístili následující soubor .htaccess:

Order Allow,Deny
Deny from all

Díky těmto direktivám zůstane adresář zvenku nepřístupný a dostane se do něj pouze aplikace.

4. Něco, co bude soubory zobrazovat

Jak jsem již zmínil výše, není nejmenší problém pomocí FileResponse soubor odeslat na výstup (tzn. do prohlížeče), bohužel díky této řádce je soubor vždy nabídnut ke stažení. Proto jsem si vytvořil svou PdfResponse, která z původní FileResponse vychází, ale snaží se soubor zobrazit místo stažení. Tuto třídu si stáhněte a umístěte do některého z adresářů app nebo libs – robot loader si je sám načte.

A je to!

Nyní bychom měli mít možnost zobrazit soubory pouze autorizovaným uživatelům. Nedaří se Vám řešení rozchodit? Napište mi to do komentářů, třeba společně najdeme řešení!