Wie man POST-Links richtig verwendet
In Webanwendungen, besonders in Administrationsoberflächen, sollte es eine Grundregel sein, dass Aktionen, die den Zustand des Servers ändern, nicht über die HTTP-Methode GET ausgeführt werden. Wie der Name der Methode nahelegt, sollte GET nur dem Abrufen von Daten dienen, nicht deren Änderung. Für Aktionen wie das Löschen von Datensätzen ist die Methode POST besser geeignet. Ideal wäre zwar die Methode DELETE, die lässt sich aber ohne JavaScript nicht auslösen, weshalb historisch POST verwendet wird.
Wie geht das in der Praxis? Nutzen Sie diesen einfachen Trick. Legen Sie am Anfang des Layout-Templates ein Hilfsformular mit
der ID postForm an, das Sie anschließend für Lösch-Schaltflächen verwenden:
<form method="post" id="postForm"></form>
Dank dieses Formulars können Sie statt eines klassischen Links <a> eine Schaltfläche
<button> verwenden, die sich optisch so gestalten lässt, dass sie wie ein gewöhnlicher Link aussieht. Das
CSS-Framework Bootstrap bietet zum Beispiel die Klassen btn btn-link, mit denen sich die Schaltfläche optisch nicht
von den übrigen Links unterscheidet. Mit dem Attribut form="postForm" verbinden wir sie mit dem vorbereiteten
Hilfsformular:
<table>
<tr n:foreach="$posts as $post">
<td>{$post->title}</td>
<td>
<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">delete</button>
<!-- instead of <a n:href="delete $post->id">delete</a> -->
</td>
</tr>
</table>
Beim Klick auf diese Schaltfläche wird nun die Aktion delete ausgelöst. Um sicherzustellen, dass Requests nur
über die Methode POST und von derselben Domain angenommen werden (was eine wirksame Abwehr gegen CSRF-Angriffe ist), verwenden
Sie das Attribut #[Requires]:
use Nette\Application\Attributes\Requires;
class AdminPresenter extends Nette\Application\UI\Presenter
{
#[Requires(methods: 'POST', sameOrigin: true)]
public function actionDelete(int $id): void
{
$this->facade->deletePost($id); // hypothetischer Code zum Löschen eines Datensatzes
$this->redirect('default');
}
}
Dieses Attribut gibt es seit Nette Application 3.2. Mehr über seine Möglichkeiten erfahren Sie auf der Seite Wie man das Attribut #Requires verwendet.
Wenn Sie statt der Aktion actionDelete() das Signal handleDelete() verwenden, ist die Angabe von
sameOrigin: true nicht nötig, denn Signale haben diesen Schutz standardmäßig aktiviert:
#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
$this->facade->deletePost($id);
$this->redirect('this');
}
Dieser Ansatz verbessert nicht nur die Sicherheit Ihrer Anwendung, sondern trägt auch zur Einhaltung korrekter Webstandards und Praktiken bei. Mit der Verwendung von POST für zustandsändernde Aktionen erreichen Sie eine robustere und sicherere Anwendung.