Wie man das #[Requires] Attribut

Wenn Sie eine Webanwendung schreiben, stoßen Sie häufig auf die Notwendigkeit, den Zugriff auf bestimmte Teile Ihrer Anwendung zu beschränken. Vielleicht möchten Sie, dass einige Anfragen nur Daten über ein Formular senden können (also die POST-Methode verwenden) oder nur für AJAX-Aufrufe zugänglich sind. In Nette Framework 3.2 wurde ein neues Werkzeug eingeführt, mit dem Sie solche Einschränkungen elegant und klar festlegen können: das #[Requires] Attribut.

Das Attribut ist eine spezielle Markierung in PHP, die Sie vor der Definition einer Klasse oder Methode hinzufügen. Da es sich im Wesentlichen um eine Klasse handelt, müssen Sie die Use-Klausel einfügen, damit die folgenden Beispiele funktionieren:

use Nette\Application\Attributes\Requires;

Sie können das #[Requires] Attribut mit der Presenter-Klasse selbst und mit diesen Methoden verwenden:

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

Die letzten beiden Methoden betreffen auch Komponenten, so dass Sie das Attribut auch für diese verwenden können.

Wenn die durch das Attribut festgelegten Bedingungen nicht erfüllt sind, wird ein HTTP 4×x-Fehler ausgelöst.

HTTP-Methoden

Sie können angeben, welche HTTP-Methoden (wie GET, POST usw.) für den Zugriff zugelassen sind. Wenn Sie beispielsweise den Zugriff nur durch das Absenden eines Formulars erlauben wollen, legen Sie fest:

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

Warum sollten Sie POST anstelle von GET für zustandsändernde Aktionen verwenden, und wie geht das? Lesen Sie den Leitfaden.

Sie können eine Methode oder eine Reihe von Methoden angeben. Ein Sonderfall ist der Wert '*', um alle Methoden zu aktivieren, was Presenter aus Sicherheitsgründen standardmäßig nicht zulassen.

AJAX-Aufrufe

Wenn Sie möchten, dass ein Presenter oder eine Methode nur für AJAX-Anfragen zugänglich ist, verwenden Sie:

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

Gleiche Herkunft

Um die Sicherheit zu erhöhen, können Sie verlangen, dass die Anfrage von der gleichen Domäne aus gestellt wird. Dies verhindert eine Anfälligkeit für CSRF:

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

Für handle<Signal>() Methoden ist der Zugriff aus derselben Domäne automatisch erforderlich. Wenn Sie also den Zugriff aus einer beliebigen Domäne zulassen wollen, geben Sie dies an:

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

Zugang über Forward

Manchmal ist es sinnvoll, den Zugriff auf einen Präsentator so einzuschränken, dass er nur indirekt verfügbar ist, z. B. über die Methoden forward() oder switch() eines anderen Präsentators. Auf diese Weise werden Fehlerpräsenter geschützt, um zu verhindern, dass sie von einer URL ausgelöst werden:

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

In der Praxis ist es oft notwendig, bestimmte Ansichten zu markieren, auf die nur aufgrund der Logik im Präsentator zugegriffen werden kann. Auch hier gilt, dass sie nicht direkt geöffnet werden können:

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

Spezifische Aktionen

Sie können auch einschränken, dass bestimmter Code, wie das Erstellen einer Komponente, nur für bestimmte Aktionen im Präsentator zugänglich ist:

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

Für eine einzelne Aktion muss kein Array geschrieben werden: #[Requires(actions: 'default')]

Benutzerdefinierte Attribute

Wenn Sie das Attribut #[Requires] Attribut wiederholt mit denselben Einstellungen verwenden möchten, können Sie ein eigenes Attribut erstellen, das die #[Requires] erbt, und es nach Ihren Bedürfnissen einstellen.

Zum Beispiel, #[SingleAction] erlaubt den Zugriff nur über die Aktion default:

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

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

Oder #[RestMethods] ermöglicht den Zugriff über alle für die REST-API verwendeten HTTP-Methoden:

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

Schlussfolgerung

Das #[Requires] Attribut gibt Ihnen große Flexibilität und Kontrolle darüber, wie auf Ihre Webseiten zugegriffen wird. Mit einfachen, aber leistungsfähigen Regeln können Sie die Sicherheit und das ordnungsgemäße Funktionieren Ihrer Anwendung verbessern. Wie Sie sehen, kann die Verwendung von Attributen in Nette Ihre Arbeit nicht nur vereinfachen, sondern auch sichern.