Le contrôleur dans l’architecture MVC

Le couche contrôleur, dans une architecture MVC comprend le systèle de routage et les différents contrôleurs associés aux actions / cas d’utilisations / routes de l’application.

Les contrôleurs sont chargés d’effectuer les vérifications nécessaires concernant les requêtes HTTP et les données transmises par le client, et le cas échéant de renvoyer un code de statut d’erreur avec la fonction http_status_code(40x), notamment :

  • 400Bad Request : lorsque les données reçues sont invalides ;
  • 400Not Found : lorsque la requête porte sur un objet qui n’existe pas ou en cas de non respect de l’intégrité référentielle.

Le contrôleur interragit :

  • avec le modèle et la couche de persistance des données — souvent assurée par un SGBD, (en utilisant éventuellement un ORM ;
  • avec la vue, responsable du rendu HTML (en utilisant éventuellement un moteur de gabarits).

Après une opération qui modifie l’état du système (création, mise-à-jour ou suppression), le contrôleur fait généralement une redirection : header('Location: /uri').

Point sur la sécurité

Ne jamais faire confiances aux données en provenance du client.

Tous les contrôles effectués côté client, que ce soit en HTML ou en Javascript servent uniquement à l’ergonomie, mais en aucun cas à la sécurité : il est (très) facile de les contourner.

Toujours considérer une utilisation malveillante par des moyens détournés :

  • javascript désactivé ;
  • édition dynamique du contenu du document ou utilisation d’un navigateur qui ignore les contraintes de saisie au niveau des formulaires ;
  • saisie manuelle d’URL (contournement des liens de l’application) ;
  • recours à des forgeurs de requêtes HTTP.

C’est le rôle du contrôleur, côté serveur, d’effectuer les vérifications nécessaires.

Formulaires, méthodes et routes

En HTML, seules les méthodes GET et POST sont utilisables pour les formulaires. Selon le style d’architecture ReST, la méthode POST sert à créer, PUT à mettre à jour et DELETE à supprimer.

Le Javascript permet d’utiliser ces méthodes, mais en attendant, le POST doit servir à toutes les opérations de changement d’état. Une solution est d’utiliser une seule route, avec un algorithme capable de déterminer l’opération à effectuer ; exemple :

  • si l’identifiant est égal à 0 et qu’il y a des données en entrée (de la requête), c’est une création ;
  • si l’identifiant est différent de 0 et qu’il y a des données en entrée, c’est une mise à jour ;
  • si l’identifiant est différent de 0 et qu’il n’y a pas des données en entrée, c’est une suppression.

Sécurité

La méthode GET ne doit jamais être utilisée pour une action qui modifie l’état du système. En effet, c’est elle qui est utilisée lors du clic sur un lien hypertexte, la saisie d’une adresse web ou le chargement de ressources externes à la page (images, CSS, javascript…). Il est facile pour un attaquant d’inciter des utilisateurs :

  • à scanner et suivre le lien contenu dans un QR-Code ;
  • d’envoyer un courriel contenant un lien hypertexte, ou une balise img qui dont la source ne pointe pas sur une image mais vers une URL d’action…

Le referer

Le “referer” est un en-tête HTTP qui indique l’URL de la page web d’où provient une requête. Lorsqu’un utilisateur clique sur un lien pour accéder à une nouvelle page, le navigateur envoie l’URL de la page d’origine via cet en-tête. Le referer est couramment utilisé pour :

  • l’analyse de trafic : il permet aux webmestres de comprendre l’origine des visites et le cheminement dans le site ;
  • la personnalisation en fonction de l’origine, ou la redirection vers la page d’origine après authentification.

Exemple en PHP :

<?php
if (isset($_SERVER['HTTP_REFERER'])) { //si le referer est défini
    $referer = $_SERVER['HTTP_REFERER'];
    echo 'Origine : ' . htmlspecialchars($referer) . '<br/>';
} else {
    echo "Aucun referer trouvé.";
}
?>

Comme tout ce qui provient du client, le referer est un vecteur d’attaque.

Filtrage et validation

La validation consiste à vérifier qu’un chaîne de caractères respecte un certain motif (cf fonction filter_var qui utilise des expressions rationnelles).

Le filtrage consiste à désactiver (échapper — cd \) ou remplacer certains caractères spéciaux / de contrôle : côte simple ou double, < (remplacé par &lt;)… Les caractères à filtrer dépendent du contexte ; exemples :

  • la fonction PDO::quote et les requêtes préparées servent à échapper les caractères spéciaux du SQL pour prévenir les injections ;
  • la fonction htmlspecialchars sert à encoder les caractères spéciaux du HTML (&&amp;, "&quot;, '&apos;, <&lt; et >&gt;) pour prévenir le XSS.

Rappel : attention à éviter le double encodage ; par exemple (en HTML) : < est encodé &lt; (“lower than”) puis &amp;lt; en cas de double encodage.