Hogyan használjuk a #[Requires] Attribútum

Webalkalmazások írása során gyakran találkozunk azzal az igénnyel, hogy korlátozni kell az alkalmazás bizonyos részeihez való hozzáférést. Talán azt szeretné, hogy egyes kérések csak űrlapon keresztül küldhessenek adatokat (tehát a POST módszerrel), vagy csak AJAX-hívások számára legyenek elérhetők. A Nette Framework 3.2-ben egy új eszköz került bevezetésre, amely lehetővé teszi az ilyen korlátozások elegáns és egyértelmű beállítását: a #[Requires] attribútum.

Az attribútum egy speciális jelölő a PHP-ban, amelyet egy osztály vagy metódus definíciója előtt adunk meg. Mivel lényegében egy osztályról van szó, a következő példák működéséhez a use záradékot is be kell illesztenie:

use Nette\Application\Attributes\Requires;

Használhatja a #[Requires] attribútumot magával a prezentáló osztállyal és ezekkel a metódusokkal:

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

Az utolsó két módszer szintén komponensekre vonatkozik, így ezekkel is használhatja az attribútumot.

Ha az attribútum által meghatározott feltételek nem teljesülnek, a rendszer egy HTTP 4×x hibaüzenetet küld.

HTTP-módszerek

Megadhatja, hogy mely HTTP-módszerek (például GET, POST stb.) engedélyezettek a hozzáféréshez. Ha például csak egy űrlap elküldésével akarja engedélyezni a hozzáférést, állítsa be a következőket:

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

Miért érdemes POST-ot használni GET helyett állapotváltoztató műveletekhez, és hogyan kell ezt megtenni? Olvassa el az útmutatót.

Megadhat egy módszert vagy módszerek tömbjét. Speciális eset a '*' érték, amely minden módszert engedélyez, amit a prezenterek biztonsági okokból alapértelmezés szerint nem engedélyeznek.

AJAX hívások

Ha azt szeretné, hogy egy bemutató vagy metódus csak AJAX-kérések számára legyen elérhető, használja a következőt:

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

Ugyanaz az eredet

A biztonság növelése érdekében megkövetelheti, hogy a kérés ugyanarról a tartományról érkezzen. Ez megakadályozza a CSRF sebezhetőséget:

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

A oldalon. handle<Signal>() módszerek esetében automatikusan ugyanabból a tartományból való hozzáférés szükséges. Ha tehát bármilyen tartományból engedélyezni szeretné a hozzáférést, adja meg:

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

Hozzáférés a Forwardon keresztül

Néha célszerű úgy korlátozni a hozzáférést egy prezentálóhoz, hogy az csak közvetve legyen elérhető, például egy másik prezentáló forward() vagy switch() módszereivel. A hiba-bemutatókat így védik, hogy megakadályozzák, hogy egy URL-ből indítsák őket:

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

A gyakorlatban gyakran szükség van bizonyos nézetek megjelölésére, amelyek csak a prezenter logikája alapján érhetők el. Megint csak azért, hogy ne lehessen őket közvetlenül megnyitni:

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ét intézkedések

Azt is korlátozhatja, hogy bizonyos kódok, például egy komponens létrehozása, csak bizonyos műveletek esetén legyenek elérhetők a prezenterben:

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

Egyetlen művelethez nem szükséges tömböt írni: #[Requires(actions: 'default')]

Egyéni attribútumok

Ha a #[Requires] attribútumot ismételten ugyanazokkal a beállításokkal használni, létrehozhat saját attribútumot, amely örökli a #[Requires] és az igényeinek megfelelően állíthatja be.

Például, #[SingleAction] csak a default műveleten keresztül engedélyezi a hozzáférést:

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

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

Vagy #[RestMethods] lehetővé teszi a hozzáférést a REST API-hoz használt összes HTTP-módszeren keresztül:

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

Következtetés

A #[Requires] attribútum nagyfokú rugalmasságot és ellenőrzést biztosít a weboldalak elérésének módját illetően. Egyszerű, de hatékony szabályok használatával fokozhatja az alkalmazás biztonságát és megfelelő működését. Amint láthatja, az attribútumok használata a Nette-ben nemcsak egyszerűsítheti, hanem biztosíthatja is a munkáját.