Kako uporabljati #[Requires] Atribut

Pri pisanju spletne aplikacije se pogosto srečate s potrebo po omejitvi dostopa do določenih delov aplikacije. Morda želite, da lahko nekatere zahteve pošljejo podatke samo prek obrazca (torej z uporabo metode POST) ali da so dostopne samo za klice AJAX. V okolju Nette Framework 3.2 je bilo uvedeno novo orodje, ki vam omogoča elegantno in jasno določanje takšnih omejitev: orodje #[Requires] atribut.

Atribut je posebna oznaka v jeziku PHP, ki jo dodate pred definicijo razreda ali metode. Ker gre v bistvu za razred, morate za delovanje naslednjih primerov vključiti klavzulo use:

use Nette\Application\Attributes\Requires;

Uporabite lahko #[Requires] atribut v samem razredu presenter in v teh metodah:

  • action<Action>()
  • render<View>()
  • handle<Signal>()
  • createComponent<Name>()

Tudi zadnji dve metodi se nanašata na komponente, zato lahko atribut uporabite tudi z njima.

Če pogoji, določeni z atributom, niso izpolnjeni, se sproži napaka HTTP 4×x.

Metode HTTP

Določite lahko, katere metode HTTP (kot so GET, POST itd.) so dovoljene za dostop. Če želite na primer dovoliti dostop samo z oddajo obrazca, nastavite:

class AdminPresenter extends Nette\Application\UI\Presenter
{
	#[Requires(methods: 'POST')]
	public function actionDelete(int $id): void
	{
	}
}

Zakaj za spreminjanje stanja uporabiti POST namesto GET in kako to storiti? Preberite vodnik.

Določite lahko metodo ali niz metod. Poseben primer je vrednost '*' za omogočanje vseh metod, ki jih predstavniki zaradi varnostnih razlogov privzeto ne omogočajo.

Klici AJAX

Če želite, da je predstavnik ali metoda dostopna samo za zahteve AJAX, uporabite:

#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}

Enako poreklo

Če želite povečati varnost, lahko zahtevate, da je zahteva poslana iz iste domene. S tem preprečite ranljivost CSRF:

#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}

Za handle<Signal>() je samodejno potreben dostop iz iste domene. Če torej želite dovoliti dostop iz katere koli domene, določite:

#[Requires(sameOrigin: false)]
public function handleList(): void
{
}

Dostop prek spletne strani Forward

Včasih je koristno omejiti dostop do predstavnika, tako da je na voljo le posredno, na primer z uporabo metod forward() ali switch() iz drugega predstavnika. Tako so predstavniki napak zaščiteni, da jih ni mogoče sprožiti z naslova URL:

#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}

V praksi je pogosto treba označiti določene poglede, do katerih je mogoče dostopati le na podlagi logike v predstavitvenem programu. Spet tako, da jih ni mogoče odpreti neposredno:

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
	{
	}
}

Posebni ukrepi

Prav tako lahko omejite, da bo določena koda, na primer ustvarjanje komponente, dostopna samo za določena dejanja v predstavitvenem programu:

class EditDeletePresenter extends Nette\Application\UI\Presenter
{
	#[Requires(actions: ['add', 'edit'])]
	public function createComponentPostForm()
	{
	}
}

Za posamezno dejanje ni treba pisati polja: #[Requires(actions: 'default')]

Atributi po meri

Če želite uporabiti #[Requires] atribut večkrat uporabiti z enakimi nastavitvami, lahko ustvarite svoj atribut, ki bo podedoval #[Requires] in ga nastavite v skladu s svojimi potrebami.

Na primer, #[SingleAction] omogoča dostop samo prek dejanja default:

#[Attribute]
class SingleAction extends Nette\Application\Attributes\Requires
{
	public function __construct()
	{
		parent::__construct(actions: 'default');
	}
}

#[SingleAction]
class SingleActionPresenter extends Nette\Application\UI\Presenter
{
}

Ali #[RestMethods] omogoči dostop prek vseh metod HTTP, ki se uporabljajo za API REST:

#[\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
{
}

Zaključek

Na spletni strani #[Requires] vam omogoča veliko prilagodljivost in nadzor nad načinom dostopa do spletnih strani. Z uporabo preprostih, a zmogljivih pravil lahko izboljšate varnost in pravilno delovanje svoje aplikacije. Kot lahko vidite, lahko z uporabo atributov v Nette ne le poenostavite svoje delo, temveč ga tudi zavarujete.