Jak používat atribut #[Requires]
Když píšete webovou aplikaci, často se setkáte s potřebou omezit přístup k určitým částem vaší
aplikace. Možná chcete, aby některé požadavky mohly odesílat data pouze pomocí formuláře (tedy metodou POST), nebo aby
byly přístupné pouze pro AJAXové volání. V Nette Frameworku 3.2 se objevil nový nástroj, který vám umožní taková
omezení nastavit velmi elegantně a přehledně: atribut #[Requires]
.
Atribut je speciální značka v PHP, kterou přidáte před definici třídy nebo metody. Protože jde vlastně o třídu, aby vám následující příklady fungovaly, je nutné uvést klauzuli use:
use Nette\Application\Attributes\Requires;
Atribut #[Requires]
můžete použít u samotné třídy presenteru a také na těchto metodách:
action<Action>()
render<View>()
handle<Signal>()
createComponent<Name>()
Poslední dvě metody se týkají i komponent, tedy atribut můžete používat i u nich.
Pokud nejsou splněny podmínky, které atribut uvádí, dojde k vyvolání HTTP chyby 4xx.
Metody HTTP
Můžete specifikovat, které HTTP metody (jako GET, POST atd.) jsou pro přístup povolené. Například, pokud chcete povolit přístup pouze odesíláním formuláře, nastavíte:
class AdminPresenter extends Nette\Application\UI\Presenter
{
#[Requires(methods: 'POST')]
public function actionDelete(int $id): void
{
}
}
Proč byste měli používat POST místo GET pro akce měnící stav a jak na to? Přečtěte si návod.
Můžete uvést metodu nebo pole metod. Speciálním případem je hodnota '*'
, která povolí všechny metody,
což standardně presentery z bezpečnostních
důvodů nedovolují.
AJAXové volání
Pokud chcete, aby byl presenter nebo metoda dostupná pouze pro AJAXové požadavky, použijte:
#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}
Stejný původ
Pro zvýšení bezpečnosti můžete vyžadovat, aby byl požadavek učiněn ze stejné domény. Tím zabráníte zranitelnosti CSRF:
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
U metod handle<Signal>()
je přístup ze stejné domény vyžadován automaticky. Takže pokud naopak
chcete povolit přístup z jakékoliv domény, uveďte:
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
Přístup přes forward
Někdy je užitečné omezit přístup k presenteru tak, aby byl dostupný pouze nepřímo, například použitím metody
forward()
nebo switch()
z jiného presenteru. Takto se třeba chrání error-presentery, aby je nebylo
možné vyvolat z URL:
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
V praxi bývá často potřeba označit určité views, ke kterým se lze dostat až na základě logiky v presenteru. Tedy opět, aby je nebylo možné otevřít přímo:
class ProductPresenter extends Nette\Application\UI\Presenter
{
public function actionDefault(int $id): void
{
$product = $this->facade->getProduct($id);
if (!$product) {
$this->setView('notfound');
}
}
#[Requires(forward: true)]
public function renderNotFound(): void
{
}
}
Konkrétní akce
Můžete také omezit, že určitý kód, třeba vytvoření komponenty, bude dostupné pouze pro specifické akce v presenteru:
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
V případě jedné akce není potřeba zapisovat pole: #[Requires(actions: 'default')]
Vlastní atributy
Pokud chcete použít atribut #[Requires]
opakovaně s týmž nastavením, můžete si vytvořit vlastní
atribut, který bude dědit #[Requires]
a nastaví ho podle potřeb.
Například #[SingleAction]
umožní přístup pouze přes akci default
:
#[\Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(actions: 'default');
}
}
#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}
Nebo #[RestMethods]
umožní přístup přes všechny HTTP metody používané pro REST API:
#[\Attribute]
class RestMethods extends Nette\Application\Attributes\Requires
{
public function __construct()
{
parent::__construct(methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
}
}
#[RestMethods]
class ApiPresenter extends Nette\Application\UI\Presenter
{
}
Závěr
Atribut #[Requires]
vám dává velkou flexibilitu a kontrolu nad tím, jak jsou vaše webové stránky
přístupné. Pomocí jednoduchých, ale mocných pravidel můžete zvýšit bezpečnost a správné fungování vaší aplikace.
Jak vidíte, použití atributů v Nette může vaši práci nejen usnadnit, ale i zabezpečit.