V kapitole Autorizace a přístupová práva byl podle pojetí [20] popsán rozdíl mezi výrazy „autorizace“ a „řízení přístupu“. Přístupový mechanizmus frameworku phpBASE vyhovuje z větší míry oběma těmto definicím. Je primárně založen na přidělování oprávnění jednotlivým uživatelům či uživatelským skupinám, což odpovídá pojetí ve smyslu autorizace. Nicméně uživatelské skupiny je zde možné definovat i jinak, než prostým výčtem jejich členů. Například právě určením IP adres, ze kterých se přistupuje, povinným zabezpečením přenosu SSL šifrováním apod. To je i v souladu s obecnější druhou definicí.
Přístupová práva v phpBASE jsou určena jednotlivými pravidly. Předpis každého pravidla má tvar:
Podoba přístupových pravidel.
V aplikaci nesmí být definována dvě pravidla, která jsou zcela stejná, nebo která se liší jen hodnotou permission. Jednotlivé položky mohou nabývat následujících hodnot:
Identifikace jednoho konkrétního uživatele, kterého se dané pravidlo týká. Položka také může nabývat hodnoty ALL, vzahuje-li se pravilo na všechny uživatele.
Identifikace jedné konkrétní uživatelské skupiny, které se dané pravidlo týká. Položka také může nabývat hodnoty ALL, jestliže se pravilo vztahuje na všechny uživatelské skupiny (resp. pokud nezáleží na zařazení uživatele do některé z uživatelských skupin).
Identifikace jedné konkrétní entity, ke které se dané pravidlo přiřazuje. Položka také může nabývat hodnoty ALL, týká-li se pravidlo všech entit.
Hodnota přístupového práva. Může být buď PERMIT (přístup povolen), nebo DENY (přístup zakázán).
Seznam přístupových pravidel v ukázkové aplikaci
Jako příklad si popíšeme tři pravidla uvedená v následující tabulce. První je nejobecnější v celé aplikaci, určuje výchozí hodnotu, není-li konkrétnějším předpisem určeno jinak. Říká, že všichni uživatelé ve všech uživatelských skupinách mají zakázaný přístup ke všem entitám. V druhém případě mají všichni uživatelé z uživatelské skupiny admin povolen přístup k modulu /main/ i ke všem jeho stránkám, není-li specifičtějším předpisem určeno jinak. A poslední pravidlo říká, že uživatel pepa, jestliže je zařazen do skupiny admin, má povolený přístup k modulu /private/. Pokud ale uživatel není členem skupiny admin, pak se ho uvedený předpis netýká a pravidlo nemá v aplikaci smysl, protože se nikdy nepoužije.
Příklad správně zadaných přístupových pravidel.
Další tři předpisy nemohou být v aplikaci definovány najednou (dokonce ani libovolné dva z nich), neboť popisují pravidla pro stejného uživatele, uživatelskou skupinu i entitu. Tím porušují výše zmíněnou zásadu unikátnosti předpisu:
Nemožná kombinace přístupových pravidel.
Pokud chceme získat pro některého uživatele či uživatelskou skupinu hodnotu přístupového práva k nějaké entitě, musíme nejdříve specifikovat dotaz na přístupové právo. Ten má tvar:
Podoba dotazu na přístupové právo.
Položky dotazu mohou nabývat konkrétních hodnot i obecné hodnoty ALL, a to navzájem v libovolné kombinaci. Dotazem se tak určí:
zda hledáme přístupové právo pro konkrétního uživatele a/nebo konkrétní uživatelskou skupinu, či pro všechny uživatele i uživatelské skupiny v aplikaci;
zda hledáme přístupové právo ke konkrétní entitě, nebo ke všem entitám v aplikaci.
Například následujícím dotazem se ptáme na přístupové právo k modulu /main/ pro všechny uživatele ze skupiny admin.
Příklad dotazu na přístupové právo k modulu /main/.
Je-li zadán konkrétní query-user a zároveň je query-group=ALL, berou se v úvahu jen skupiny, do kterých je zadaný uživatel přiřazený, nikoliv všechny skupiny v celé aplikaci. Následující dotaz tedy hledá hodnotu přístupového práva k modulu /private/ pro uživatele pepa ve všech uživatelských skupinách, do kterých je zařazen.
Příklad dotazu na přístupové právo pro uživatele pepa.
V praxi se samozřejmě daleko nejčastěji používají dotazy na přístupové právo ke konkrétní komponentě pro aktuálního uživatele ve všech jeho skupinách. Ostatní varianty jsou k dispozici víceméně pro úplnost.
Výsledkem dotazu je vždy hodnota přístupového práva pro zadané parametry, tzn. jedna z hodnot PERMIT nebo DENY. Ta se určí takto:
Vyberou se všechna relevantní pravidla, která odpovídají zadanému dotazu.
Z nich se vybere nejspecifičtější pravidlo.
Jeho hodnota se vrátí jako výsledné přístupové právo.
Pravidla relevantní zadanému dotazu jsou všechna pravidla definovaná v aplikaci, pro která zároveň platí:
Položka user je buď ALL, nebo je rovna položce dotazu query-user.
Jestliže je v dotazu zadána konkrétní uživatelská skupina, pak group v pravidle je buď ALL, nebo je rovna položce dotazu query-group.
Jestliže není v dotazu zadána konkrétní uživatelská skupina a zároveň je v dotazu určen konkrétní uživatel, pak group pravidla je ALL nebo je rovna identifikátoru některé z uživatelských skupin, do kterých je tento uživatel zařazen.
Jestliže není v dotazu zadána konkrétní uživatelská skupina ani uživatel, pak group pravidla je ALL.
Položka entity je buď ALL, nebo je rovna položce dotazu query-entity či některému z předků entity query-entity.
Zde je nutné vysvětlit pojem „předek entity“. Při výchozí konfiguraci phpBASE se přístupová práva dědí jen z modulu na jeho vlastní komponenty a akce, ale už nikoliv na podmoduly a jejich komponenty a akce. Máme-li tedy například stránku /news/admin/index, pak přístup k ní žádným způsobem neovlivní pravidlo definované pro modul /news/. Jestliže je ale v konfiguraci frameworku nastavena direktiva APP_INHERIT, pak se přístupová práva na dědí nejen z daného modulu na komponenty a akce přímo v něm, ale i na všechny jeho podmoduly a jejich komponenty a akce. Neboli při dotazu na stránku /news/admin/index přichází v úvahu i pravidla určená pro modul /news/.
V další fázi ze všech relevantních pravidel vybereme to nejspecifičtější. Tedy konkrétnější pravidlo má přednost před obecnějšími. Zásady uspořádání jsou následující (dříve uvedená zásada má vyšší prioritu):
Pravidlo pro konkrétního uživatele je specifičtější, než pravidlo s položkou user=ALL.
Pravidlo pro konkrétní uživatelskou skupinu je specifičtější, než pravidlo s položkou group=ALL. U více různých konkrétních skupin se pravidla seřadí podle předem pevně daného pořadí těchto skupin.
Pravidlo pro konkrétní entitu je specifičtější, než pravidlo s položkou entity=ALL. Přitom potomek entity je specifičtější, než jeho předek.
Přednost uživatelů před entitami při vyhodnocování přístupu.
Z uvedených zásad je patrné, že uživatelská část pravidla má přednost před částí entitní. Například z následujících dvou pravidel je první specifičtější. Toto by se stejně dobře mohlo udělat i úplně naopak, tedy předností entitní části před uživatelskou (pak by třetí zásada uspořádání byla na prvním místě). Zvolený přístup však více odpovídá intuitivnímu chápání priorit pravidel.
Konečnou hodnotou přístupového práva získaného k zadanému dotazu je hodnota nejspecifičtějšího relevantního pravidla.
Grafický přehled vyhodnocování výsledného práva k jednotlivým entitám pro zadaného uživatele
Může však dojít k situaci, že k zadanému dotazu nebude nalezeno ani jedno definované pravidlo. Pak přichází na řadu implicitní zákaz přístupu, neboli je vráceno DENY. Implicitní zákaz existuje z bezpečnostních důvodů. Je totiž mnohem bezpečnější mít vše zakázáno a pak postupně přístup k jednotlivým entitám pro jednotlivé uživatele či skupiny povolovat. V opačném případě (při implicitním PERMIT a explicitním zakazování) reálně hrozí, že administrátor přístup do některé chráněné oblasti zapomene zakázat či takovou chybu přehlédne. A obecně zde platí zásada „least privileges“ [20], neboli přidělení jen nejnutnějších oprávnění. Lépe je tak omylem nezpřístupnit jinak veřejnou část aplikace, než omylem zpřístupnit část citlivou.
Pro zjištění přístupového práva k určité entitě definuje framework funkci Perm. Tu lze použít v libovolné stránce, skriptu i knihovně. Prvním parametrem funkce je identifikátor entity. Implicitně se dotaz vyhodnocuje pro aktuálního uživatele. Volitelným druhým a třetím parametrem lze ale zadat i jiného uživatele resp. uživatelskou skupinu. Funkce vrací příslušnou booleovskou hodnotu. V následujícím příkladu první příkaz vrátí přístupové právo ke komponentě /main/index pro aktuálního uživatele, druhý zjistí přístup ke stejné komponentě, ale pro uživatele číslo 1.
<?php
Perm("/main/index");
Perm("/main/index", 1);
?>
Obsah stránek vyjadřuje osobní názory, postoje a zkušenosti autora. Copyright © 2004–2010 Jan Tichý.