Kako pravilno uporabljati POST povezave
V spletnih aplikacijah, zlasti v administrativnih vmesnikih, bi moralo biti osnovno pravilo, da se akcije, ki spreminjajo stanje strežnika, ne izvajajo prek metode HTTP GET. Kot pove že ime metode, bi moral GET služiti samo za pridobivanje podatkov, ne pa za njihovo spreminjanje. Za akcije, kot je na primer brisanje zapisov, je primernejša uporaba metode POST. Čeprav bi bila idealna metoda DELETE, je te brez JavaScripta ni mogoče izvesti, zato se zgodovinsko uporablja POST.
Kako to storiti v praksi? Uporabite ta preprost trik. Na začetku predloge si ustvarite pomožni obrazec z identifikatorjem
postForm
, ki ga nato uporabite za gumbe za brisanje:
<form method="post" id="postForm"></form>
Zahvaljujoč temu obrazcu lahko namesto klasične povezave <a>
uporabite gumb <button>
,
ki ga lahko vizualno prilagodite tako, da izgleda kot običajna povezava. Na primer, CSS ogrodje Bootstrap ponuja razreda
btn btn-link
, s katerima dosežete, da gumb ne bo vizualno drugačen od ostalih povezav. Z atributom
form="postForm"
ga povežemo z vnaprej pripravljenim obrazcem:
<table>
<tr n:foreach="$posts as $post">
<td>{$post->title}</td>
<td>
<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">izbriši</button>
<!-- namesto <a n:href="delete $post->id">izbriši</a> -->
</td>
</tr>
</table>
Ob kliku na povezavo se zdaj izvede akcija delete
. Za zagotovitev, da bodo zahteve sprejete samo prek metode POST
in iz iste domene (kar je učinkovita obramba pred napadi CSRF), uporabite atribut #[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); // hipotetična koda, ki briše zapis
$this->redirect('default');
}
}
Atribut obstaja od Nette Application 3.2 in več o njegovih možnostih boste izvedeli na strani Kako uporabljati atribut #Requires.
Če bi namesto akcije actionDelete()
uporabljali signal handleDelete()
, ni treba navajati
sameOrigin: true
, ker imajo signali to zaščito nastavljeno implicitno:
#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
$this->facade->deletePost($id);
$this->redirect('this');
}
Ta pristop ne samo izboljšuje varnost vaše aplikacije, ampak tudi prispeva k spoštovanju pravilnih spletnih standardov in praks. Z uporabo metod POST za akcije, ki spreminjajo stanje, dosežete bolj robustno in varnejšo aplikacijo.