Hogyan használjuk helyesen a POST linkeket

Webalkalmazásokban, különösen adminisztrációs felületeken, alapvető szabálynak kellene lennie, hogy a szerver állapotát megváltoztató műveleteket ne a GET HTTP metódussal végezzük. Ahogy a metódus neve is sugallja, a GET csak adatok lekérésére szolgál, nem pedig azok megváltoztatására. Olyan műveletekhez, mint például a rekordok törlése, célszerűbb a POST metódust használni. Bár ideális a DELETE metódus lenne, de azt JavaScript nélkül nem lehet meghívni, ezért történelmileg a POST-ot használják.

Hogyan tegyük ezt a gyakorlatban? Használja ezt az egyszerű trükköt. A sablon elején hozzon létre egy segédűrlapot postForm azonosítóval, amelyet aztán a törlő gombokhoz használ:

<form method="post" id="postForm"></form>

Ennek az űrlapnak köszönhetően a klasszikus <a> link helyett használhat egy <button> gombot, amelyet vizuálisan úgy lehet módosítani, hogy úgy nézzen ki, mint egy normál link. Például a Bootstrap CSS keretrendszer btn btn-link osztályokat kínál, amelyekkel elérheti, hogy a gomb vizuálisan ne különbözzön a többi linktől. A form="postForm" attribútummal összekapcsoljuk az előkészített űrlappal:

<table>
	<tr n:foreach="$posts as $post">
		<td>{$post->title}</td>
		<td>
			<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">törlés</button>
			<!-- <a n:href="delete $post->id">törlés</a> helyett -->
		</td>
	</tr>
</table>

A linkre kattintva most a delete akció hívódik meg. Annak biztosítására, hogy a kérések csak a POST metóduson keresztül és ugyanarról a domainről érkezzenek (ami hatékony védelem a CSRF támadások ellen), használja a #[Requires] attribútumot:

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); // hipotetikus kód a rekord törlésére
		$this->redirect('default');
	}
}

Az attribútum a Nette Application 3.2 óta létezik, és további lehetőségeiről a Hogyan használjuk a #Requires attribútumot oldalon olvashat többet.

Ha az actionDelete() akció helyett a handleDelete() signált használná, nem szükséges megadni a sameOrigin: true-t, mert a signáloknak ez a védelme alapértelmezetten be van állítva:

#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
	$this->facade->deletePost($id);
	$this->redirect('this');
}

Ez a megközelítés nemcsak javítja az alkalmazás biztonságát, hanem hozzájárul a helyes webes szabványok és gyakorlatok betartásához is. A POST metódusok használatával az állapotot megváltoztató műveletekhez robusztusabb és biztonságosabb alkalmazást érhet el.