Cum se utilizează #[Requires] Atributul

Atunci când scrieți o aplicație web, vă confruntați adesea cu necesitatea de a restricționa accesul la anumite părți ale aplicației. Poate doriți ca unele cereri să poată trimite date doar prin intermediul unui formular (utilizând astfel metoda POST) sau să fie accesibile doar apelurilor AJAX. În Nette Framework 3.2, a fost introdus un nou instrument care vă permite să stabiliți astfel de restricții în mod elegant și clar: instrumentul #[Requires] atribut.

Atributul este un marker special în PHP, pe care îl adăugați înainte de definiția unei clase sau metode. Deoarece este în esență o clasă, trebuie să includeți clauza use pentru ca următoarele exemple să funcționeze:

use Nette\Application\Attributes\Requires;

Puteți utiliza funcția #[Requires] cu clasa presenter în sine și cu aceste metode:

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

Ultimele două metode se referă, de asemenea, la componente, astfel încât puteți utiliza atributul și cu acestea.

În cazul în care condițiile specificate de atribut nu sunt îndeplinite, se declanșează o eroare HTTP 4xx.

Metode HTTP

Puteți specifica ce metode HTTP (cum ar fi GET, POST etc.) sunt permise pentru acces. De exemplu, dacă doriți să permiteți accesul numai prin trimiterea unui formular, setați:

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

De ce ar trebui să folosiți POST în loc de GET pentru acțiunile de schimbare a stării și cum să faceți acest lucru? Citiți ghidul.

Puteți specifica o metodă sau o serie de metode. Un caz special este valoarea '*' pentru a activa toate metodele, pe care prezentatorii nu o permit în mod implicit din motive de securitate.

Apeluri AJAX

Dacă doriți ca un prezentator sau o metodă să fie accesibilă numai pentru cererile AJAX, utilizați:

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

Aceeași origine

Pentru a spori securitatea, puteți solicita ca solicitarea să fie făcută din același domeniu. Acest lucru previne vulnerabilitatea la CSRF:

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

Pentru handle<Signal>() este necesar în mod automat accesul din același domeniu. Prin urmare, dacă doriți să permiteți accesul din orice domeniu, specificați:

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

Acces prin Forward

Uneori este util să se restricționeze accesul la un prezentator astfel încât acesta să fie disponibil doar indirect, de exemplu, prin utilizarea metodelor forward() sau switch() de la un alt prezentator. Acesta este modul în care sunt protejați prezentatorii de erori pentru a împiedica declanșarea lor de la un URL:

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

În practică, este adesea necesar să se marcheze anumite vizualizări care pot fi accesate numai pe baza logicii din prezentator. Din nou, pentru ca acestea să nu poată fi deschise direct:

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

Acțiuni specifice

Puteți, de asemenea, să restricționați accesul la anumite coduri, cum ar fi crearea unei componente, numai pentru anumite acțiuni din prezentator:

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

Pentru o singură acțiune, nu este nevoie să scrieți o matrice: #[Requires(actions: 'default')]

Atribute personalizate

Dacă doriți să utilizați #[Requires] în mod repetat cu aceleași setări, puteți crea propriul atribut care va moșteni atributul #[Requires] și să îl setați în funcție de nevoile dumneavoastră.

De exemplu, #[SingleAction] permite accesul numai prin intermediul acțiunii default:

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

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

Sau #[RestMethods] va permite accesul prin toate metodele HTTP utilizate pentru 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
{
}

Concluzie

The #[Requires] vă oferă o mare flexibilitate și control asupra modului în care sunt accesate paginile dvs. web. Utilizând reguli simple, dar puternice, puteți spori securitatea și buna funcționare a aplicației dumneavoastră. După cum puteți vedea, utilizarea atributelor în Nette nu numai că vă poate simplifica munca, dar o poate și securiza.