Wie man das Attribut #[Requires] verwendet
Wenn Sie eine Webanwendung schreiben, stoßen Sie oft auf die Notwendigkeit, den Zugriff auf bestimmte Teile
Ihrer Anwendung einzuschränken. Vielleicht wollen Sie, dass manche Requests Daten nur über ein Formular senden können (also mit
der Methode POST) oder nur für AJAX-Aufrufe zugänglich sind. Im Nette Framework 3.2 ist ein neues Werkzeug erschienen, 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 setzen. Da es sich im
Grunde um eine Klasse handelt, müssen Sie die use-Klausel angeben, damit die folgenden Beispiele funktionieren:
use Nette\Application\Attributes\Requires;
Das Attribut #[Requires] können Sie bei der Presenter-Klasse selbst und außerdem bei diesen Methoden
verwenden:
action<Action>()render<View>()handle<Signal>()createComponent<Name>()
Die letzten beiden Methoden betreffen auch Komponenten, Sie können das Attribut also auch bei ihnen einsetzen.
Sind die Bedingungen, die das Attribut angibt, nicht erfüllt, 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 zum Beispiel den Zugriff nur über das Absenden eines Formulars erlauben wollen, setzen Sie:
class AdminPresenter extends Nette\Application\UI\Presenter
{
#[Requires(methods: 'POST')]
public function actionDelete(int $id): void
{
}
}
Warum Sie für zustandsändernde Aktionen POST statt GET verwenden sollten und wie das geht? 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 aus
Sicherheitsgründen standardmäßig nicht zulassen.
AJAX-Aufrufe
Wenn Sie wollen, dass ein Presenter oder eine Methode nur für AJAX-Requests zugänglich 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 der Request von derselben Domain kommt. Damit verhindern Sie die CSRF-Sicherheitslücke:
#[Requires(sameOrigin: true)]
class SecurePresenter extends Nette\Application\UI\Presenter
{
}
Bei handle<Signal>()-Methoden wird der Zugriff von derselben Domain automatisch verlangt. Wenn Sie umgekehrt
den Zugriff von jeder beliebigen Domain erlauben wollen, geben Sie an:
#[Requires(sameOrigin: false)]
public function handleList(): void
{
}
Zugriff über forward
Manchmal ist es nützlich, den Zugriff auf einen Presenter so einzuschränken, dass er nur indirekt verfügbar ist, zum
Beispiel über die Methoden forward() oder switch() aus einem anderen Presenter. So werden etwa
Error-Presenter geschützt, damit sie sich nicht über eine URL aufrufen lassen:
#[Requires(forward: true)]
class ForwardedPresenter extends Nette\Application\UI\Presenter
{
}
In der Praxis ist es oft nötig, bestimmte Views zu kennzeichnen, zu denen man erst aufgrund der Logik im Presenter gelangt. Also wiederum so, dass sie sich nicht direkt öffnen lassen:
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 außerdem einschränken, dass bestimmter Code, etwa das Erstellen einer Komponente, nur für bestimmte Aktionen im Presenter verfügbar ist:
class EditDeletePresenter extends Nette\Application\UI\Presenter
{
#[Requires(actions: ['add', 'edit'])]
public function createComponentPostForm()
{
}
}
Bei einer einzelnen Aktion muss kein Array geschrieben werden: #[Requires(actions: 'default')]
Eigene Attribute
Wenn Sie das Attribut #[Requires] wiederholt mit denselben Einstellungen verwenden wollen, können Sie sich ein
eigenes Attribut erstellen, das #[Requires] erbt und nach Ihren Bedürfnissen konfiguriert.
Zum Beispiel erlaubt #[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 eine REST-API 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 Ihre Webseiten zugänglich
sind. Mit einfachen, aber mächtigen Regeln können Sie die Sicherheit und das korrekte Funktionieren Ihrer Anwendung verbessern.
Wie Sie sehen, kann die Verwendung von Attributen in Nette Ihre Arbeit nicht nur erleichtern, sondern auch absichern.