Comment utiliser correctement les liens POST
Dans les applications web, en particulier dans les interfaces d'administration, une règle de base devrait être que les actions modifiant l'état du serveur ne devraient pas être effectuées via la méthode HTTP GET. Comme le nom de la méthode l'indique, GET devrait servir uniquement à obtenir des données, non à les modifier. Pour des actions telles que la suppression d'enregistrements, il est préférable d'utiliser la méthode POST. Bien que l'idéal serait la méthode DELETE, mais elle ne peut pas être invoquée sans JavaScript, c'est pourquoi POST est historiquement utilisé.
Comment faire en pratique ? Utilisez cette astuce simple. Au début du template de votre layout, créez un formulaire
auxiliaire avec l'identifiant postForm
, que vous utiliserez ensuite pour les boutons de suppression :
<form method="post" id="postForm"></form>
Grâce à ce formulaire, vous pouvez utiliser un bouton <button>
au lieu d'un lien classique
<a>
, qui peut être visuellement stylisé pour ressembler à un lien normal. Par exemple, le framework CSS
Bootstrap propose les classes btn btn-link
avec lesquelles vous obtiendrez que le bouton ne soit pas visuellement
différent des autres liens. À l'aide de l'attribut form="postForm"
, nous le lions au formulaire
pré-préparé :
<table>
<tr n:foreach="$posts as $post">
<td>{$post->title}</td>
<td>
<button class="btn btn-link" form="postForm" formaction="{link delete $post->id}">supprimer</button>
<!-- au lieu de <a n:href="delete $post->id">supprimer</a> -->
</td>
</tr>
</table>
En cliquant sur le bouton, l'action delete
est maintenant invoquée. Pour garantir que les requêtes ne soient
acceptées que via la méthode POST et depuis le même domaine (ce qui est une défense efficace contre les attaques CSRF),
utilisez l'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); // code hypothétique supprimant l'enregistrement
$this->redirect('default');
}
}
L'attribut existe depuis Nette Application 3.2 et vous en apprendrez plus sur ses possibilités sur la page Comment utiliser l'attribut #Requires.
Si vous utilisiez le signal handleDelete()
au lieu de l'action actionDelete()
, il n'est pas
nécessaire d'indiquer sameOrigin: true
, car les signaux ont cette protection définie implicitement :
#[Requires(methods: 'POST')]
public function handleDelete(int $id): void
{
$this->facade->deletePost($id);
$this->redirect('this');
}
Cette approche améliore non seulement la sécurité de votre application, mais contribue également au respect des normes et pratiques web correctes. En utilisant les méthodes POST pour les actions modifiant l'état, vous obtiendrez une application plus robuste et plus sûre.