Nette Documentation Preview

syntax
Kako uporabljati atribut `#[Requires]`
**************************************

.[perex]
Ko pišete spletno aplikacijo, se pogosto srečate s potrebo po omejitvi dostopa do določenih delov vaše aplikacije. Morda želite, da lahko nekateri zahtevki pošiljajo podatke samo s pomočjo obrazca (torej z metodo POST), ali da so dostopni samo za AJAX klice. V Nette Frameworku 3.2 se je pojavilo novo orodje, ki vam omogoča takšne omejitve nastaviti zelo elegantno in pregledno: atribut `#[Requires]`.

Atribut je posebna oznaka v PHP, ki jo dodate pred definicijo razreda ali metode. Ker gre pravzaprav za razred, da bi vam naslednji primeri delovali, je treba navesti klavzulo use:

```php
use Nette\Application\Attributes\Requires;
```

Atribut `#[Requires]` lahko uporabite pri samem razredu presenterja in tudi na teh metodah:

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

Zadnji dve metodi se nanašata tudi na komponente, torej atribut lahko uporabljate tudi pri njih.

Če pogoji, ki jih atribut navaja, niso izpolnjeni, pride do sprožitve HTTP napake 4xx.


Metode HTTP
-----------

Lahko specificirate, katere HTTP metode (kot GET, POST itd.) so za dostop dovoljene. Na primer, če želite dovoliti dostop samo s pošiljanjem obrazca, nastavite:

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

Zakaj bi morali uporabljati POST namesto GET za akcije, ki spreminjajo stanje, in kako to storiti? [Preberite navodilo |post-links].

Lahko navedete metodo ali polje metod. Poseben primer je vrednost `'*'`, ki dovoli vse metode, kar standardno presenterji iz [varnostnih razlogov ne dovoljujejo |application:presenters#Preverjanje HTTP metode].


AJAX klici
----------

Če želite, da je presenter ali metoda dostopna samo za AJAX zahtevke, uporabite:

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


Isti izvor
----------

Za povečanje varnosti lahko zahtevate, da je zahtevek narejen iz iste domene. S tem preprečite [ranljivost CSRF |nette:vulnerability-protection#Cross-Site Request Forgery CSRF]:

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

Pri metodah `handle<Signal>()` je dostop iz iste domene zahtevan samodejno. Torej, če nasprotno želite dovoliti dostop iz katerekoli domene, navedite:

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


Dostop prek posredovanja
------------------------

Včasih je koristno omejiti dostop do presenterja tako, da je dostopen samo posredno, na primer z uporabo metode `forward()` ali `switch()` iz drugega presenterja. Tako se na primer ščitijo error-presenterji, da jih ni mogoče poklicati iz URL-ja:

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

V praksi je pogosto treba označiti določene poglede (views), do katerih je mogoče priti šele na podlagi logike v presenterju. Torej spet, da jih ni mogoče odpreti neposredno:

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


Konkretne akcije
----------------

Lahko tudi omejite, da bo določena koda, na primer ustvarjanje komponente, dostopna samo za specifične akcije v presenterju:

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

V primeru ene akcije ni treba zapisovati polja: `#[Requires(actions: 'default')]`


Lastni atributi
---------------

Če želite atribut `#[Requires]` uporabiti večkrat z isto nastavitvijo, si lahko ustvarite lasten atribut, ki bo dedoval `#[Requires]` in ga nastavil po potrebi.

Na primer `#[SingleAction]` bo omogočil dostop samo prek akcije `default`:

```php
#[\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]` bo omogočil dostop prek vseh HTTP metod, uporabljenih za REST API:

```php
#[\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
---------

Atribut `#[Requires]` vam daje veliko fleksibilnosti in nadzora nad tem, kako so vaše spletne strani dostopne. S pomočjo preprostih, a močnih pravil lahko povečate varnost in pravilno delovanje vaše aplikacije. Kot vidite, lahko uporaba atributov v Nette vaše delo ne samo olajša, ampak tudi zavaruje.

{{sitename: Best Practices}}

Kako uporabljati atribut #[Requires]

Ko pišete spletno aplikacijo, se pogosto srečate s potrebo po omejitvi dostopa do določenih delov vaše aplikacije. Morda želite, da lahko nekateri zahtevki pošiljajo podatke samo s pomočjo obrazca (torej z metodo POST), ali da so dostopni samo za AJAX klice. V Nette Frameworku 3.2 se je pojavilo novo orodje, ki vam omogoča takšne omejitve nastaviti zelo elegantno in pregledno: atribut #[Requires].

Atribut je posebna oznaka v PHP, ki jo dodate pred definicijo razreda ali metode. Ker gre pravzaprav za razred, da bi vam naslednji primeri delovali, je treba navesti klavzulo use:

use Nette\Application\Attributes\Requires;

Atribut #[Requires] lahko uporabite pri samem razredu presenterja in tudi na teh metodah:

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

Zadnji dve metodi se nanašata tudi na komponente, torej atribut lahko uporabljate tudi pri njih.

Če pogoji, ki jih atribut navaja, niso izpolnjeni, pride do sprožitve HTTP napake 4xx.

Metode HTTP

Lahko specificirate, katere HTTP metode (kot GET, POST itd.) so za dostop dovoljene. Na primer, če želite dovoliti dostop samo s pošiljanjem obrazca, nastavite:

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

Zakaj bi morali uporabljati POST namesto GET za akcije, ki spreminjajo stanje, in kako to storiti? Preberite navodilo.

Lahko navedete metodo ali polje metod. Poseben primer je vrednost '*', ki dovoli vse metode, kar standardno presenterji iz varnostnih razlogov ne dovoljujejo.

AJAX klici

Če želite, da je presenter ali metoda dostopna samo za AJAX zahtevke, uporabite:

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

Isti izvor

Za povečanje varnosti lahko zahtevate, da je zahtevek narejen iz iste domene. S tem preprečite ranljivost CSRF:

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

Pri metodah handle<Signal>() je dostop iz iste domene zahtevan samodejno. Torej, če nasprotno želite dovoliti dostop iz katerekoli domene, navedite:

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

Dostop prek posredovanja

Včasih je koristno omejiti dostop do presenterja tako, da je dostopen samo posredno, na primer z uporabo metode forward() ali switch() iz drugega presenterja. Tako se na primer ščitijo error-presenterji, da jih ni mogoče poklicati iz URL-ja:

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

V praksi je pogosto treba označiti določene poglede (views), do katerih je mogoče priti šele na podlagi logike v presenterju. Torej spet, 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
	{
	}
}

Konkretne akcije

Lahko tudi omejite, da bo določena koda, na primer ustvarjanje komponente, dostopna samo za specifične akcije v presenterju:

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

V primeru ene akcije ni treba zapisovati polja: #[Requires(actions: 'default')]

Lastni atributi

Če želite atribut #[Requires] uporabiti večkrat z isto nastavitvijo, si lahko ustvarite lasten atribut, ki bo dedoval #[Requires] in ga nastavil po potrebi.

Na primer #[SingleAction] bo omogočil dostop samo prek akcije 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] bo omogočil dostop prek vseh HTTP metod, uporabljenih za 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
{
}

Zaključek

Atribut #[Requires] vam daje veliko fleksibilnosti in nadzora nad tem, kako so vaše spletne strani dostopne. S pomočjo preprostih, a močnih pravil lahko povečate varnost in pravilno delovanje vaše aplikacije. Kot vidite, lahko uporaba atributov v Nette vaše delo ne samo olajša, ampak tudi zavaruje.