Nette Documentation Preview

syntax
Come usare l'attributo `#[Requires]`
************************************

.[perex]
Quando scrivete un'applicazione web, capita spesso di dover limitare l'accesso a certe sue parti. Magari volete che alcune richieste possano inviare dati solo tramite un form (cioè con il metodo POST), oppure che siano accessibili solo alle chiamate AJAX. In Nette Framework 3.2 è comparso un nuovo strumento che permette di impostare limiti del genere in modo elegante e chiaro: l'attributo `#[Requires]`.

Un attributo è un contrassegno particolare in PHP che si scrive prima della definizione di una classe o di un metodo. Poiché si tratta in sostanza di una classe, perché gli esempi seguenti funzionino occorre indicare la clausola `use`:

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

L'attributo `#[Requires]` si può usare sulla classe stessa del presenter e su questi metodi:

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

Gli ultimi due metodi riguardano anche i componenti, quindi potete usare l'attributo pure con essi.

Se le condizioni indicate dall'attributo non sono soddisfatte, viene generato un errore HTTP 4xx.


Metodi HTTP
-----------

Potete indicare quali metodi HTTP (come GET, POST ecc.) sono ammessi per l'accesso. Se per esempio volete consentire l'accesso solo tramite l'invio di un form, impostate:

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

Perché per le azioni che cambiano lo stato dovreste usare POST invece di GET e come farlo? [Leggete la guida |post-links].

Potete indicare un metodo oppure un array di metodi. Un caso particolare è il valore `'*'`, che consente tutti i metodi, cosa che i presenter [per motivi di sicurezza non permettono per impostazione predefinita |application:presenters#Controllo del metodo HTTP].


Chiamate AJAX
-------------

Se volete che un presenter o un metodo sia accessibile solo per le richieste AJAX, usate:

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


Stessa origine
--------------

Per aumentare la sicurezza potete richiedere che la richiesta provenga dallo stesso dominio. Così eviterete la [vulnerabilità CSRF |nette:vulnerability-protection#Cross-Site Request Forgery (CSRF)]:

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

Per i metodi `handle<Signal>()` l'accesso dallo stesso dominio è richiesto automaticamente. Se quindi volete consentire l'accesso da qualsiasi dominio, indicate:

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


Accesso tramite forward
-----------------------

A volte è utile limitare l'accesso a un presenter in modo che sia disponibile solo indirettamente, per esempio con i metodi `forward()` o `switch()` da un altro presenter. Così si proteggono per esempio i presenter di errore, perché non sia possibile richiamarli da URL:

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

Nella pratica capita spesso di dover contrassegnare certe viste alle quali si può accedere solo in base alla logica del presenter. Anche in questo caso perché non si possano aprire direttamente:

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


Azioni specifiche
-----------------

Potete anche limitare un certo codice, per esempio la creazione di un componente, in modo che sia accessibile solo per determinate azioni del presenter:

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

Nel caso di una sola azione non serve scrivere un array: `#[Requires(actions: 'default')]`


Attributi propri
----------------

Se volete usare l'attributo `#[Requires]` ripetutamente con le stesse impostazioni, potete creare un vostro attributo che eredita da `#[Requires]` e lo configura secondo le vostre esigenze.

Per esempio `#[SingleAction]` consente l'accesso solo tramite l'azione `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
{
}
```

Oppure `#[RestMethods]` consentirà l'accesso con tutti i metodi HTTP usati per le API REST:

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


Conclusione
-----------

L'attributo `#[Requires]` vi dà grande flessibilità e controllo su come si accede alle vostre pagine web. Con regole semplici ma efficaci potete aumentare la sicurezza e il corretto funzionamento della vostra applicazione. Come vedete, usare gli attributi in Nette può non solo semplificare il vostro lavoro, ma anche renderlo più sicuro.

Come usare l'attributo #[Requires]

Quando scrivete un'applicazione web, capita spesso di dover limitare l'accesso a certe sue parti. Magari volete che alcune richieste possano inviare dati solo tramite un form (cioè con il metodo POST), oppure che siano accessibili solo alle chiamate AJAX. In Nette Framework 3.2 è comparso un nuovo strumento che permette di impostare limiti del genere in modo elegante e chiaro: l'attributo #[Requires].

Un attributo è un contrassegno particolare in PHP che si scrive prima della definizione di una classe o di un metodo. Poiché si tratta in sostanza di una classe, perché gli esempi seguenti funzionino occorre indicare la clausola use:

use Nette\Application\Attributes\Requires;

L'attributo #[Requires] si può usare sulla classe stessa del presenter e su questi metodi:

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

Gli ultimi due metodi riguardano anche i componenti, quindi potete usare l'attributo pure con essi.

Se le condizioni indicate dall'attributo non sono soddisfatte, viene generato un errore HTTP 4xx.

Metodi HTTP

Potete indicare quali metodi HTTP (come GET, POST ecc.) sono ammessi per l'accesso. Se per esempio volete consentire l'accesso solo tramite l'invio di un form, impostate:

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

Perché per le azioni che cambiano lo stato dovreste usare POST invece di GET e come farlo? Leggete la guida.

Potete indicare un metodo oppure un array di metodi. Un caso particolare è il valore '*', che consente tutti i metodi, cosa che i presenter per motivi di sicurezza non permettono per impostazione predefinita.

Chiamate AJAX

Se volete che un presenter o un metodo sia accessibile solo per le richieste AJAX, usate:

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

Stessa origine

Per aumentare la sicurezza potete richiedere che la richiesta provenga dallo stesso dominio. Così eviterete la vulnerabilità CSRF:

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

Per i metodi handle<Signal>() l'accesso dallo stesso dominio è richiesto automaticamente. Se quindi volete consentire l'accesso da qualsiasi dominio, indicate:

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

Accesso tramite forward

A volte è utile limitare l'accesso a un presenter in modo che sia disponibile solo indirettamente, per esempio con i metodi forward() o switch() da un altro presenter. Così si proteggono per esempio i presenter di errore, perché non sia possibile richiamarli da URL:

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

Nella pratica capita spesso di dover contrassegnare certe viste alle quali si può accedere solo in base alla logica del presenter. Anche in questo caso perché non si possano aprire direttamente:

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

Azioni specifiche

Potete anche limitare un certo codice, per esempio la creazione di un componente, in modo che sia accessibile solo per determinate azioni del presenter:

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

Nel caso di una sola azione non serve scrivere un array: #[Requires(actions: 'default')]

Attributi propri

Se volete usare l'attributo #[Requires] ripetutamente con le stesse impostazioni, potete creare un vostro attributo che eredita da #[Requires] e lo configura secondo le vostre esigenze.

Per esempio #[SingleAction] consente l'accesso solo tramite l'azione default:

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

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

Oppure #[RestMethods] consentirà l'accesso con tutti i metodi HTTP usati per le 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
{
}

Conclusione

L'attributo #[Requires] vi dà grande flessibilità e controllo su come si accede alle vostre pagine web. Con regole semplici ma efficaci potete aumentare la sicurezza e il corretto funzionamento della vostra applicazione. Come vedete, usare gli attributi in Nette può non solo semplificare il vostro lavoro, ma anche renderlo più sicuro.