src/Security/Authorization/Voter/ClientIpVoter.php line 16

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by PhpStorm.
  4.  * User: Ninon
  5.  * Date: 22/03/2017
  6.  * Time: 15:16
  7.  */
  8. namespace App\Security\Authorization\Voter;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. class ClientIpVoter extends Voter
  13. {
  14.     const ALLOW 'allow';
  15.     const DENY 'deny';
  16.     /**
  17.      * @var array
  18.      */
  19.     protected $_sListeIPs;
  20.     /**
  21.      * ClientIpVoter constructor.
  22.      *
  23.      * @param array $aListeIPs
  24.      */
  25.     public function __construct(array $aListeIPs)
  26.     {
  27.         $this->_sListeIPs $aListeIPs;
  28.     }
  29.     /**
  30.      * Determines if the attribute and subject are supported by this voter.
  31.      *
  32.      * @param string $attribute An attribute
  33.      * @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
  34.      *
  35.      * @return bool True if the attribute and subject are supported, false otherwise
  36.      */
  37.     protected function supports(string $attribute$subject)
  38.     {
  39.         // if the attribute isn't one we support, return false
  40.         if (!in_array($attribute, [self::ALLOWself::DENY])) {
  41.             return false;
  42.         }
  43.         // only vote on `Request` objects
  44.         if (!$subject instanceof Request) {
  45.             return false;
  46.         }
  47.         return true;
  48.     }
  49.     /**
  50.      * Perform a single access check operation on a given attribute, subject and token.
  51.      * It is safe to assume that $attribute and $subject already passed the "supports()" method check.
  52.      *
  53.      * @param mixed $subject
  54.      *
  55.      * @return bool
  56.      */
  57.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token)
  58.     {
  59.         // you know $subject is a Post object, thanks to `supports()`
  60.         /** @var Request $request */
  61.         $request $subject;
  62.         $route $request->get('_route');
  63.         if ($route === 'admin_noutonline_version'){
  64.             switch ($attribute)
  65.             {
  66.                 case self::ALLOW:
  67.                     return true;
  68.                 case self::DENY:
  69.                     return false;
  70.             }
  71.         }
  72.         $sClientIP $request->getClientIp();
  73.         $bMatche false;
  74.         foreach($this->_sListeIPs as $range)
  75.         {
  76.             if ($this->_bTestIP($sClientIP$range)){
  77.                 $bMatche true;
  78.                 break;
  79.             }
  80.         }
  81.         switch ($attribute)
  82.         {
  83.             case self::ALLOW:
  84.                 return $bMatche;
  85.             case self::DENY:
  86.                 return !$bMatche;
  87.         }
  88.         return false;
  89.     }
  90.     /**
  91.      * transforme une ip en chaine binaire
  92.      * @param $sIP
  93.      * @return string
  94.      */
  95.     protected function _sIP2bits($sIP)
  96.     {
  97.         $cx strpos($sIP'/');
  98.         if (!$cx)
  99.         {
  100.             $in_addr inet_pton($sIP);
  101.             return bin2hex($in_addr);
  102.         }
  103.         // Strip out the netmask, if there is one.
  104.         $subnet = (int)(substr($sIP$cx+1));
  105.         $ipaddr substr($sIP0$cx);
  106.         $in_addr inet_pton($ipaddr);
  107.         $aByteAddr str_split($in_addr);
  108.         // Maximum netmask length = same as packed address
  109.         $len 8*strlen($in_addr);
  110.         if ($subnet $len){
  111.             $subnet $len;
  112.         }
  113.         // Create a hex expression of the subnet mask
  114.         $mask  str_repeat('f'$subnet>>2);
  115.         switch($subnet 3)
  116.         {
  117.         case 3$mask .= 'e'; break;
  118.         case 2$mask .= 'c'; break;
  119.         case 1$mask .= '8'; break;
  120.         }
  121.         $mask str_pad($mask$len>>2'0');
  122.         // Packed representation of netmask
  123.         $mask pack('H*'$mask);
  124.         $aByteMask str_split($mask);
  125.         $sIpRes '';
  126.         for ($i=$i<count($aByteAddr) ; $i++)
  127.         {
  128.             $nValIp ord($aByteAddr[$i]);
  129.             $nValMasque = isset($aByteMask[$i]) ? ord($aByteMask[$i]) : 0;
  130.             $sIpRes.= str_pad(dechex($nValIp $nValMasque), 2'0'STR_PAD_LEFT);
  131.         }
  132.         return $sIpRes;
  133.     }
  134.     /**
  135.      * Compare l'ip du client avec le range
  136.      * @param $clientIP
  137.      * @param $range
  138.      * @return bool
  139.      */
  140.     protected function _bTestIP($clientIP$range)
  141.     {
  142.         $cx strpos($range'/');
  143.         if ($cx){
  144.             $clientIP .= substr($range$cx);
  145.         }
  146.         $sBinClientIp $this->_sIP2bits($clientIP);
  147.         $sBinRange $this->_sIP2bits($range);
  148.         return strcasecmp($sBinClientIp$sBinRange)==0;
  149.     }
  150. }