Symfony Event Subscriber | Restriction d’une plage ip avec un Event Subscriber

Ajout d’un Event Subscriber sous Symfony avec restriction de plage IP

Dans le cadre du tutoriel, nous allons mettre en place une restriction de plage IP pour autoriser certaines IP, mais vous pouvez utiliser les Event subscriber
dans n’importe quel cas. Un Event subscriber permet d’executer du code avant de rentrer dans notre route d’un controller par exemple, il nous permet de vérifier certaines
choses tel que la connexion en token, et toutes autres sortes de manipulations.

Ajout du fichier SecureIpSubscriber.php

Il vous faut commencer par ajouter un dossier EventSubscriber dans le dossier src de votre projet Symfony (Ou bien où vous le souhaitez mais c’est plus rapide ici).
Et ensuite ajouter le fichier suivant :

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class SecureIpSubscriber implements EventSubscriberInterface
{
    public function onKernelController($event)
    {
        // Ajouter votre code ici
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => 'onKernelController',
        ];
    }
}

Vous pouvez voir que notre classe SecureIpSubscriber implemente obligatoirement l’interface EventSubscriberInterface
Et que grace à la fonction static getSubscribedEvents, nous connaissons l’event sur lequel la classe écoute, il existe plusieurs events Symfony
Le code qui sera executé lors de l’écoute sur cet event est présent dans la fonction onKernelController, nous allons donc voir comment restreindre les ip !

Définition des plages ip et ajout d’une fonction de tri

Pour restreindre les plages ip nous devons d’abord connaitre quelles plages restreindre :

class SecureIpSubscriber implements EventSubscriberInterface
{
    private $ips = array(
        array('deb' => '125.1.0.1', 'fin' => '125.158.3.254'),
        array('deb' => '192.168.5.1', 'fin' => '192.168.160.254'),
    );

    /**
    Code ...
    */
}

Nous ajoutons donc une variable privée qui permet de définir deux plages ip, nous pourrions en ajouter autant que voulue.
Et ensuite nous avons besoin d’une fonction (qui n’est pas de moi) qui va permettre de trier les ip dans notre tableau.

    //Check plage ip
    private function verifPlageIP($IP, $PlageIP)
    {
        $result = true;
        $tabIP = explode(".", $IP);
        if (is_array($PlageIP)) {
            foreach ($PlageIP as $valeur) {
                $tabPlageIP[] = explode(".", $valeur);
            }
            for ($i = 0; $i < 4; $i++) {
                if (($tabIP[$i] < $tabPlageIP[0][$i]) || ($tabIP[$i] > $tabPlageIP[1][$i])) {
                    $result = FALSE;
                }
            }
        } else {
            $tabPlageIP = explode(".", $PlageIP);
            for ($i = 0; $i < 4; $i++) {
                if (($tabIP[$i] != $tabPlageIP[$i])) {
                    $result = FALSE;
                }
            }
        }
        return ($result);
    }

Et une fois nos plages définies et la fonction verifPlageIp dans notre classe, nous pouvons écrire le code dans le onKernelController :

    //On check l'ip seulement sur la route de l'api
    public function onKernelController($event)
    {
        //On check l'ip seulement sur la route de l'api
        if ($event->getRequest()->get('_route') == "api") {
            $ip = $_SERVER['REMOTE_ADDR'];
            $valid = false;
            // localhost
            if ($ip == '::1' || $ip == '127.0.0.1') {
                $valid = true;
            } else {
                foreach ($this->ips as $plage) {
                    $valid = $this->verifPlageIP($ip, $plage);
                    if ($valid === true) break;
                }
            }

            if ($valid === false) {
                exit();
            }
        }
    }

Dans mon cas nous pouvons voir que j’ai restreint l’ip pour une seule route, mais il est possible de supprimer cette condition pour que cela soit applicable à l’ensemble de 
l’application, ou bien en rajouter d’autres au choix.
Nous vérifions donc si l’ip est localhost ou bien dans une plage ip, si c’est bon on continue dans notre route qui pourrait nous retourner des données d’une API et dans
le cas contraire le code est exit et la personne ne reçoit rien.

Ce tutoriel est maintenant terminé, merci d’avoir lu et n’hésitez pas à le partager !