Wie man das Attribut #[Requires]
verwendet
Beim Schreiben einer Webanwendung stoßen Sie oft auf die Notwendigkeit, den Zugriff auf bestimmte Teile Ihrer
Anwendung zu beschränken. Vielleicht möchten Sie, dass einige Anfragen nur über ein Formular (also mit der POST-Methode) Daten
senden können oder nur für AJAX-Aufrufe zugänglich sind. Im Nette Framework 3.2 gibt es ein neues Werkzeug, mit dem Sie solche
Einschränkungen sehr elegant und übersichtlich festlegen können: das Attribut #[Requires]
.
Ein Attribut ist eine spezielle Markierung in PHP, die Sie vor die Definition einer Klasse oder Methode hinzufügen. Da es sich eigentlich um eine Klasse handelt, müssen Sie für die Funktion der folgenden Beispiele die use-Klausel angeben:
use Nette\Application\Attributes\Requires;
Das Attribut #[Requires]
können Sie bei der Presenter-Klasse selbst und auch bei diesen Methoden verwenden:
action<Action>()
render<View>()
handle<Signal>()
createComponent<Name>()
Die letzten beiden Methoden betreffen auch Komponenten, das Attribut können Sie also auch bei ihnen verwenden.
Wenn die im Attribut angegebenen Bedingungen nicht erfüllt sind, wird ein HTTP-Fehler 4xx ausgelöst.
HTTP-Methoden
Sie können angeben, welche HTTP-Methoden (wie GET, POST usw.) für den Zugriff erlaubt sind. Wenn Sie beispielsweise den Zugriff nur durch das Absenden eines Formulars erlauben möchten, stellen Sie ein:
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 Aktionen verwenden, die den Zustand ändern, und wie geht das? Lesen Sie die Anleitung.
Sie können eine Methode oder ein Array von Methoden angeben. Ein Sonderfall ist der Wert '*'
, der alle Methoden
erlaubt, was Presenter standardmäßig aus Sicherheitsgründen nicht
zulassen.
AJAX-Aufrufe
Wenn Sie möchten, dass ein Presenter oder eine Methode nur für AJAX-Anfragen verfügbar ist, verwenden Sie:
#[Requires(ajax: true)]
class AjaxPresenter extends Nette\Application\UI\Presenter
{
}
Gleicher Ursprung
Zur Erhöhung der Sicherheit können Sie verlangen, dass die Anfrage von derselben Domain stammt. Dadurch verhindern Sie CSRF-Schwachstellen:
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
Bei handle<Signal>()
-Methoden wird der Zugriff von derselben Domain automatisch verlangt. Wenn Sie also den
Zugriff von jeder beliebigen Domain erlauben möchten, geben Sie an:
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
Zugriff über forward
Manchmal ist es nützlich, den Zugriff auf einen Presenter so zu beschränken, dass er nur indirekt verfügbar ist,
beispielsweise durch Verwendung der Methode forward()
oder switch()
aus einem anderen Presenter. So
werden beispielsweise Error-Presenter geschützt, damit sie nicht über die URL aufgerufen werden können:
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
In der Praxis ist es oft notwendig, bestimmte Views zu markieren, auf die erst aufgrund der Logik im Presenter zugegriffen werden kann. Also wieder, damit 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
{
}
}
Konkrete Aktionen
Sie können auch einschränken, dass bestimmter Code, wie das Erstellen einer Komponente, nur für spezifische Aktionen im Presenter verfügbar ist:
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
Im Falle einer einzelnen Aktion ist es nicht notwendig, ein Array zu
schreiben: #[Requires(actions: 'default')]
Eigene Attribute
Wenn Sie das Attribut #[Requires]
wiederholt mit denselben Einstellungen verwenden möchten, können Sie ein
eigenes Attribut erstellen, das #[Requires]
erbt und es nach Bedarf konfiguriert.
Beispielsweise ermöglicht #[SingleAction]
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]
erlaubt den Zugriff über alle HTTP-Methoden, die für REST-APIs verwendet werden:
#[\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
{
}
Fazit
Das Attribut #[Requires]
gibt Ihnen große Flexibilität und Kontrolle darüber, wie auf Ihre Webseiten
zugegriffen wird. Mit einfachen, aber leistungsstarken Regeln können Sie die Sicherheit und die korrekte Funktion Ihrer Anwendung
erhöhen. Wie Sie sehen, kann die Verwendung von Attributen in Nette Ihre Arbeit nicht nur erleichtern, sondern auch sicherer
machen.