Jak správně nastavit privátní systém souborů v Drupalu a k čemu je to dobré

Drupal již od starších verzí umožňuje nastavit dvoje hlavní složky pro ukládání souborů. Výchozí je veřejná, druhá je privátní. Bohužel i řada letitých drupalistů stále neví, k čemu je toto rozdělení dobré a k čemu privátní soubory slouží. Pokusím se to vysvětlit.

Reklama

Souborová struktura redakčního systému Drupal se skládá z několika složek s kódem v PHP a ze souborového úložiště. Ve starších verzích to byla složka files umístěná přímo v kořenové složce webu, od Drupalu 6 je to obvykle složka sites/default/files. Samozřejmě v závislosti na konkrétní implementaci Drupalu se to může lišit – umístění souborové složky lze v nastavení snadno změnit.

Do složky se systémem souborů je nahráván veškerý obsah, který kopírujete přes webové rozhraní administrace. Tedy samozřejmě ne texty a nastavení, ale obrázky, videa, dokumenty a další přílohy obsahu.

K čemu slouží privátní systém souborů v Drupalu

Když se podíváte do nastavení v Drupalu 7, konkrétně do části Konfigurace » Média » Systém souborů, pak si určitě všimnete, že kromě zmíněné složky s veřejným systémem souborů je zde možné nastavit i cestu k privátnímu systému souborů.

Jakmile sem vložíte nějakou cestu ke složce, do které se budou privátní soubory nahrávat, pak při definici obrázkových nebo jiných souborových polí se vás bude Drupal ptát, zda se mají kopírovat do veřejného nebo privátního systému souborů.

Když něco nahrajete do běžného veřejného systému souborů, tedy typicky do sites/default/files, pak je takový soubor jednoduše dostupný přes webový prohlížeč. Stačí, aby k němu uživatel znal nebo odhadl cestu. U obrázků to asi tolik nevadí, ale pokud si postavíte eshop s prodejem digitálních produktů ke stažení nebo chcete ukládat pravidelné zálohy databáze nebo jiný citlivý obsah, pak asi nechcete, aby si jej mohl kdokoli jen tak stáhnout zadáním adresy do webového prohlížeče.

A právě tento problém řeší privátní systém souborů. Když do něj něco nahrajete, pak to ve výsledku má nějakou na pohled běžnou adresu, ale je zde jeden podstatný rozdíl. Při požadavku na privátní soubor totiž dojde ke kompletnímu načtení jádra Drupalu. Soubory tedy neservíruje přímo webový prohlížeč.

Tím, že se načte Drupal, může zkontrolovat, zda se k souboru snaží dostat například přihlášený uživatel, který na to má oprávnění (správce pro obnovu zálohy, zákazník, který si zakoupil soubor pro stažení a podobně).

Já privátní systém souborů využívám v praxi nejčastěji k ukládání pravidelných záloh databáze pomocí modulu Backup and Migrate. Několikrát jsem stavěl eshop s již zmíněným stahováním zakoupených souborů. A rovněž jsem stavěl weby, kde bylo potřeba nahrávat speciální dokumenty určené jen nějaké skupince lidí, kteří se přihlásí do webu. Jistě vás napadne něco dalšího.

Poznámka: Ukládání zálohy databáze na stejné místo, kde běží web, je samozřejmě samo o sobě k ničemu. Když spadne server či hosting, přijdete i o onu zálohu. Já to však dělám proto, že mám zálohován ještě celý server a navíc si celou složku webu i s privátním systémem souborů pravidelně stahuji přes rsync do počítače.

Častá chyba v nastavení privátního systému souborů

Bohužel poměrně často narážím na weby, které sice privátní systém souborů využívají, ale mají jej nastaven takovým způsobem, že jeho smysl ochranné funkce a kontroly přístupu je potlačen. Jak je to možné? Tyto weby totiž mají jako privátní systém souborů nastaveno sites/default/files/private. Už vám svítá?

Pokud totiž nějaký soubor leží přímo v souborové struktuře Drupalu, lze se k němu teoreticky dostat zadáním jeho přímé adresy do prohlížeče. Pokud ji uhodnete nebo znáte, pak vám webový server vrátí rovnou daný soubor pro stažení, nenahraje se Drupal a neověří, zda vůbec máte právo k souboru přistupovat.

Problém vzniká obvykle tím, že na většině hostingů totiž nemůžete z Drupalu přistupovat jinam, něž je přidělená složka pro umístění webové prezentace. Například u Wedosu to ale možné je, ideální řešení je použít vlastní server (třeba Maxiorel běží u Linode).

Když vám to hosting umožní, pak si vytvořte například složku private mimo umístění, kde je nahrán web. Poté přejděte do Konfigurace » Média » Systém souborů a do políčka Cesta k privátnímu systému souborů zadejte relativní cestu k vytvořené složce vzhledem k adresáři s Drupalem. Pokud tedy máte Drupal ve složce www a na stejné úrovni je složka private, pak zadáte ../private.

Privátní systém souborů v Drupalu

No a to je vše. Protože privátní složka leží mimo složku s webem, nelze se do ní dostat přes webový prohlížeč a při požadavku s URL adresou na privátní soubor vstoupí do hry Drupal. Zkontroluje, zda na něj máte právo a pak vám jej teprve vrátí.

Lámete si hlavu, jak je to možné, když přeci máte nějakou URL, která vede někam do Drupalu? Není to samozřejmě kouzlo. Daný modul Drupalu z URL pozná, že odkazuje na privátní soubor, podívá se do privátní složky a soubor případně vrátí, jako kdyby se k němu přistupovalo přímo.

Tagy: 

Reklama

Komentáře

Dobrý den,
dovolím si nesouhlasit.
Ve složce pro Private files se automaticky vytvoří .htacesss soubor, který zabraňuje přímému přístupu k souboru. Takže i když znáte správnou URL, soubor nelze stáhnout. to jde opravdu jen přes Drupalí funkce, které soubor naservírují.
Pak už samozřejmě na nastavení dalších oprávnění k daným souborům.

Já bych to řekl asi takto:
public files - soubory lze stáhnout přímo přes URL
private files - soubory "servíruje" nějaká funkce. Pokud chcete omezit přístup, musíte sáhnout k nějakému dodatečnému modulu.

Zajímavé moduly pro tuto tématiku:
content_access
private_files_download_permission

Vše potřebné je v oficiální dokumentaci https://www.drupal.org/documentation/modules/file
viz Managing file locations and access a Accessing Private Files

Platí přinejmenším pro kombinaci Drupal 7 a Apache

Tak nesouhlasit samozřejmě můžete :) To, co říkáte, je v podstatě pravda. Na druhou stranu v tom ale vidím minimálně dva problémy:
1. Spousta hostingů má problémy se zpracováním výchozího .htaccessu v souborovém systému u Drupalu, takže pak se to vyřadí z činnosti
2. Může dojít k nějakému problému na serveru, který vyřadí .htaccess z činnosti a soubory pak budou volně přístupné

Nemám s tím mimo Apache zkušenosti - funguje toto pravidlo v .htaccess, i pokud je webserverem nginx?

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

S nginxem to nefunguje, takže správně je ../private a ../tmp

Tak jsem rád, že mám zastánce :-) Je to prostě univerzální řešení, než spoléhat na .htaccess.

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

Mám weby na C4.cz a vznesl jsem tento požadavek na foru http://forum.c4.cz/drupal-privatni-system-souboru-a-neverejna-slozka-t51... a obratem mi nabídli řešení, které spočívá ve změně document root např. do složky www a vedle ní je vytvořená složka private. Dokonce mi i existující weby přesunuli do této nové složky.

Dobré vědět, díky.

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

Zdravím,
již dříve jsem četl Váš článek a dle Vašich dobrých rad jsem nastavoval privátní systém souborů mimo výchozí složku.
Na hostingu mám přístupnou výchozí složku, kde mám možnost si vytvořit další podsložky. Je zde také složka "www", která je určená pro nahrání webu (zde mám logicky Drupal 7). V Drupalu 7 mám nastavenu cestu k privátnímu souborovému systému jako "../data-private" je lepší použít tento zápis nebo "/data-private" ještě drobnost - má uvedená cesta končit "/" nebo ne?
-----
Pak druhá - hlavní otázka:
Jak nastavit modul Backup and Migrate aby zálohoval současně databázi, veřejné i soukromé soubory? Když jsem v modulu nastavil Entire site (code, files & DB) tak složka (/data-private), která je mimo výchozí složku drupalu (/www)zálohována není.
V záloze, kterou jsem stáhl z NodeSquirrel má v MANIFEST.ini řádek files-private = "docroot/../data-private" a složka s privátnímu soubory v archivu není.
-----
Předem díky moc za Váš čas a odpověď, případně nasměrování.
-----
PS: bylo by dobrým řešením nastavit privátní složku jako např. /sites/default/files-private?

Zdravím. K prvnímu dotazu - /data-private by hledalo cestu přímo v kořenové složce celého serveru, což asi není to správné a složka asi ani neexistujte. Tedy použijte ../data-private, coby relativní cestu vzhledem k Drupalu. Lomítko na konec nedávejte.

Druhá otázka - to asi neporadím, Backup and Migrate jsem v souvislosti s privátními soubory asi nepoužil. A klienti většinou spoléhají na zálohování hostingu či svého serveru, takže Backup and Migrate mají jen na databázi pro případ, že by něco sami pohnojili a potřebovali obnovit.

/sites/default/files-private taky může být privátní složka, mám pocit, že tam Drupal dá .htaccess, který zaručí, že to nebude vidět přímým zadáním URL adresy. Nicméně je to podle mého názoru risk. Stačí chybka v .htaccessu nebo jej webserver začne ignorovat a rázem ta složka bude přístupná. Kdežto, když je mimo web, tak už technicky přes prohlížeč přístupná být nemůže.

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

Dobrý den,
privátní soubory mám nastaveny, jak je popsáno výše. Existuje možnost, jak logovat přístupy k těmto souborům (mimo standardní log), např. posláním e-mailu na administrátorskou adresu, ve kterém by bylo kdo, kdy, jak...? Jestliže Drupal tyto soubory "servíruje" a přístupy k nim v logu najdu, tak předpokládám že ano, jen nevím, jak toho docílit.

Dobrý den,
zkuste mrknout na tento patch pro modul Rules https://www.drupal.org/project/rules/issues/1267650

Případně si napište jednoduchý modul s využitím hook_file_download https://api.drupal.org/api/drupal/modules!system!system.api.php/function…

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

Zvolil jsem druhou cestu a už to "něco" dělá.
V Rules mám nadefinováno pravidlo pro přístup k privátnímu souboru, jako Event nastaveno Content is viewed pro konkrétní stránku (typ obsahu). Podmínka Elements obsahuje User has field access, Parametr: Entity: [node], Název pole: field_dokument, Hodnota: Zobrazit.
V tělu e-mailu je pak, mimo jiné, nahrazovací vzor: [node:field_dokument] pro zobrazení onoho dokumentu.
Jak jsem psal, zvolil jsem druhou cestu, ale uvedený hook už v mé verzi Drupalu byl a takto nastavené pravidlo mi do e-mailu vypisovalo Property 0 až 4, tedy (při své chabé angličtině) se domnívám, že to popisuje poznámka v diskusi od markj.
Proto jsem zkusil implementovat kód od agileadam do template v mém tématu a ejhle...
V e-mailu se objevily odkazy na všechny soubory z pole field_document, hezky oddělené čárkami.
Sláva, jenže já potřebuju vědět, jaký konkrétní soubor si uživatel prohlíží, poněvadž je jich 200.

Argumentem funkce hook_file_download() je přece adresa na ten soubor ve tvaru URI. Když jej vezmete a vložíte do drupal_basename(), dostanete jen název souboru https://api.drupal.org/api/drupal/includes%21file.inc/function/drupal_ba…

Tvořím weby. Nabízím poradenství pro Drupal. Jsem na Twitteru.

Přidat komentář