src/Controller/SecurityController.php line 35

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. // begin token-guard ---------------------------------------------------------------------------------
  4. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  5. use Symfony\Component\Security\Csrf\CsrfToken;
  6. use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
  7. use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
  8. // end token-guard ---------------------------------------------------------------------------------
  9. use App\Service\LOGDEFService;
  10. use App\Service\DIVService;
  11. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  12. use Symfony\Component\Routing\Annotation\Route;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  16. use Doctrine\Persistence\ManagerRegistry;
  17. use Symfony\Component\Validator\Validator\ValidatorInterface;       // contrôleur de contraintes
  18. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;   // l'encodeur ofcourse
  19. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  20. use App\Entity\usr;
  21. use App\Entity\usl;
  22. class SecurityController extends AbstractController
  23. {
  24.     #[Route(path'/identification'name'identification')]
  25.     public function identification
  26.         (
  27.             ManagerRegistry $doctrine
  28.             AuthenticationUtils $authenticationUtils,
  29.             UserPasswordHasherInterface $passwordHasher,
  30.             DIVService $divservice,
  31.         ): Response
  32.     {
  33.         
  34.         $em $doctrine->getManager();
  35.         // activer si besoin de coder / définir un pwd pour un glups
  36.         /*
  37.             $usr = $em->getRepository(usr::class)->findOneBy(array('username'=>'stephy.deveaux'));
  38.             $plaintextPassword = 'agagagagag:';
  39.             $hashedPassword = $passwordHasher->hashPassword(
  40.                 $usr,
  41.                 $plaintextPassword
  42.             );
  43.             $usr->setPassword($hashedPassword);
  44.             $em->persist($usr);
  45.             $em->flush();
  46.         */
  47.         // =============== CTRL LOGIN'S =====================
  48.         //var_dump($_SERVER);
  49.         // vérif occurences demandes : combien de fois en combien de temps pour quel login
  50.         $delaymin 1800;    // délai maxi pour une série de tentative de login pour une IP (30')
  51.         $nbtryipmax 16;      // nb tentatives max pour une même IP en moins de 'delaymin'
  52.         $nbtrylogmax 10;      // nb tentatives échouées max pour un login en moins de 'delaymin'
  53.         
  54.         $ip '';
  55.         if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){    // récup IP origine dde
  56.             $ip $_SERVER['HTTP_X_FORWARDED_FOR'];
  57.         }else{
  58.             $ip $_SERVER['REMOTE_ADDR'];
  59.         }
  60.         $datnow time();
  61.         $perioddde date('Y-m-d H:i:s'mktime(date('H'$datnow),date('i'$datnow),date('s'$datnow),date('m'$datnow),date('d'$datnow),date('Y'$datnow)));
  62.         $datlimit $datnow $delaymin;
  63.         $periodlimit date('Y-m-d H:i:s'mktime(date('H'$datlimit),date('i'$datlimit),date('s'$datlimit),date('m'$datlimit),date('d'$datlimit),date('Y'$datlimit)));
  64.         // 1° niveau CTRL : affichage répété page login pour rien  ================================
  65.         $ctx '';$nbtry=0;
  66.         if((isset($_SERVER['HTTP_REFERER'])) && (isset($_SERVER['HTTP_COOKIE']))){ // logout possible, pas de vérif
  67.             $ctx 'logout';
  68.             // dd('http referer isset et cookie');
  69.         }
  70.         
  71.         // nb ddes pour cette IP dans les dernières 'delaymin' secondes avec ou sans login
  72.         if($ctx!='logout'){
  73.             // dd($ctx.', '.$ip);
  74.             $query $em->getRepository(usl::class)->createQueryBuilder('usl')
  75.                 ->select("COUNT(usl.uslip) AS nbtry")
  76.                 ->where('usl.uslip = :uslip')
  77.                 ->setParameter('uslip'$ip)
  78.                 ->andwhere('usl.uslip NOT IN (:iplocale)')
  79.                 // ->setParameter('iplocale' , array('127.0.0.1','192.168.26.50'))     // pour audit cq + locloc
  80.                 ->setParameter('iplocale' , array('127.0.0.1'))     // locloc ou cq
  81.                 ->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
  82.                 ->setParameter('perioddde' ,$perioddde)
  83.                 ->setParameter('periodlimit' ,$periodlimit)
  84.             ;
  85.             $nbtry $query->getQuery()->getSingleScalarResult();
  86.         }
  87.         // 1° blocage : affichage excessif de la page de login pour rien
  88.         if($nbtry>=$nbtryipmax){        // abus
  89.             $this->addFlash('Erreur'"IP Reconnectez-vous dans 1 heure. Tentatives de connexion excessives : ".$nbtryipmax);
  90.             // renvoi page erreur
  91.             return $this->render('security/erreur.html.twig'
  92.                 array(
  93.                     'ip' => $ip
  94.                 )
  95.             );
  96.         }
  97.         
  98.         // 2° niveau CTRL : tentative de login répétée avec échec => error ========================
  99.         // vérif si même IP a tenté de se loguer plus de nbtrylogmax pour un login avec N comptes....
  100.         $query $em->getRepository(USL::class)->createQueryBuilder('usl')
  101.             ->select("COUNT(usl.uslip) AS nbtry")
  102.             ->where('usl.uslctx =:uslctx')
  103.             ->setParameter('uslctx''error')
  104.             ->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
  105.             ->setParameter('perioddde' ,$perioddde)
  106.             ->setParameter('periodlimit' ,$periodlimit)
  107.         ;
  108.         $nbtry $query->getQuery()->getSingleScalarResult();
  109.         if($nbtry>=$nbtrylogmax){        // abus
  110.             $this->addFlash('Erreur'"IP Reconnectez-vous dans 1 heure. Tentatives de connexion excessives : ".$nbtrylogmax);
  111.             // renvoi page erreur
  112.             return $this->render('security/erreur.html.twig'
  113.                 array(
  114.                     'ip' => $ip
  115.                 )
  116.             );
  117.         }else{
  118.             
  119.             // enregistrement des caractéristiques de la demande de login 
  120.             $error $authenticationUtils->getLastAuthenticationError();    // get the login error if there is one
  121.             $lastUsername $authenticationUtils->getLastUsername();        // last username entered by the user
  122.             // possible provenance logout, récup phpsessid pour id usr
  123.             $cook ''
  124.             if(isset($_SERVER['HTTP_REFERER'])){
  125.                 if(isset($_SERVER['HTTP_COOKIE'])){ // id usr possibl
  126.                     $cook str_replace('PHPSESSID=','',$_SERVER['HTTP_COOKIE']);
  127.                     $pos strpos($cook";");
  128.                     if(($pos>1)&&($pos<255)){
  129.                         $cook substr($cook0$pos-1);
  130.                     }else{
  131.                         $cook substr($cook0254);
  132.                     }
  133.                 }
  134.             }
  135.             if($error){                                                // inactive renvoi erreur niveau Render (ci-dessous)
  136.                 $login $lastUsername;
  137.                 $ctx 'error';
  138.                 $this->addFlash('Erreur''Identification invalide');
  139.             }else{
  140.                 if($lastUsername!=''){
  141.                     $login $lastUsername;
  142.                     $ctx 'login';
  143.                     if($cook==''){
  144.                         $ctx 'start';
  145.                     }
  146.                 }else{
  147.                     $login '';
  148.                     if($cook==''){
  149.                         $ctx 'start';
  150.                     }else{
  151.                         $ctx 'logout';
  152.                     }
  153.                 }
  154.             }
  155.             
  156.         
  157.             // enrgt dde : IP + Heure + login (0,1)
  158.             $datdde = new \DateTime();
  159.             $usl = new usl;
  160.             $usl->setUslip($ip);
  161.             $usl->setUsldat($datdde);
  162.             $usl->setUsllogin($login);
  163.             $usl->setUslctx($ctx);
  164.             $usl->setUslcook($cook);
  165.             $em->persist($usl);
  166.             $em->flush();
  167.             // 2° niveau vérif   ================================
  168.             // nb échecs pour ce login dans les dernières 'delaymin' secondes
  169.             $nbtry 0;
  170.             if($login!=''){
  171.                 $query $em->getRepository(USL::class)->createQueryBuilder('usl')
  172.                     ->select("COUNT(usl.uslip) AS nbtry")
  173.                     ->where('usl.usllogin = :usllogin')
  174.                     ->setParameter('usllogin'$login)
  175.                     ->andwhere('usl.uslctx <> :uslctx')
  176.                     ->setParameter('uslctx''error')
  177.                     ->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
  178.                     ->setParameter('perioddde' ,$perioddde)
  179.                     ->setParameter('periodlimit' ,$periodlimit)
  180.                 ;
  181.                 $nbtry $query->getQuery()->getSingleScalarResult();
  182.             }
  183.                     
  184.             if($nbtry>=$nbtrylogmax){
  185.                 $this->addFlash('Erreur'"LOGIN : Reconnectez-vous dans 1 heure, nb tentatives excessives > ".$nbtrylogmax);
  186.                 // renvoi page erreur
  187.                 return $this->render('security/erreur.html.twig'
  188.                     array(
  189.                         'ip' => $ip
  190.                     )
  191.                 );
  192.             }else{
  193.                 
  194.                 // situation normale ras
  195.                 return $this->render('security/login.html.twig', [
  196.                     'last_username' => $lastUsername,
  197.                     'error' => $error,
  198.                     // 'deflog' => $deflog,
  199.                 ]);
  200.             }
  201.         }
  202.     }
  203.     #[Route(path'/login'name'app_login')]
  204.     public function login
  205.         (
  206.             AuthenticationUtils $authenticationUtils,
  207.             LOGDEFService $logdefservice,
  208.             DIVService $divservice,
  209.         ): Response
  210.     {
  211.         
  212.         // en cas d'erreur, enregistrement des caractéristiques de la demande de login 
  213.         // TODO : tenter de réafficher identification !?
  214.         $error $authenticationUtils->getLastAuthenticationError();    // get the login error if there is one
  215.         $lastUsername $authenticationUtils->getLastUsername();        // last username entered by the user
  216.         // ACCUEIL : possible provenance logout, récup phpsessid pour id usr
  217.         $cook ''
  218.         if(isset($_SERVER['HTTP_REFERER'])){
  219.             if(isset($_SERVER['HTTP_COOKIE'])){ // id usr possibl
  220.                 $cook str_replace('PHPSESSID=','',$_SERVER['HTTP_COOKIE']);
  221.                 $pos strpos($cook";");
  222.                 if(($pos>1)&&($pos<255)){
  223.                     $cook substr($cook0$pos-1);
  224.                 }else{
  225.                     $cook substr($cook0254);
  226.                 }
  227.             }
  228.         }
  229.         if($error){                                                // inactive renvoi erreur niveau Render (ci-dessous)
  230.             $login $lastUsername;
  231.             $ctx 'error';
  232.             $this->addFlash('Erreur''Identification invalide');
  233.         }else{
  234.             if($lastUsername!=''){
  235.                 $login $lastUsername;
  236.                 $ctx 'login';
  237.                 if($cook==''){
  238.                     $ctx 'start';
  239.                 }
  240.             }else{
  241.                 $login '';
  242.                 if($cook==''){
  243.                     $ctx 'start';
  244.                 }else{
  245.                     $ctx 'logout';
  246.                 }
  247.             }
  248.         }
  249.         // OUTILS : infobulles fusion de la page
  250.         $lesdefs = array('ppi','pfb','mfp');
  251.         $deflog = array();
  252.         foreach($lesdefs as $ladef){
  253.             $deflog[$ladef] = $logdefservice->get_unedef($ladef); 
  254.         }
  255.         
  256.         // récup guide pratique CF
  257.         $gp $divservice->crypt_cfppiid(57);
  258.         
  259.         return $this->render('security\accueil.html.twig', array(
  260.                 'last_username' => $lastUsername,
  261.                 'deflog' => $deflog,
  262.                 'error' => $error,
  263.                 'gp' => $gp
  264.             )
  265.         ); 
  266.     }
  267.     
  268.     // les cartes à jouer avec les outils financiers
  269.     #[Route(path'/nosoutils'name'nosoutils')]
  270.     public function nosoutils(
  271.             LOGDEFService $logdefservice,
  272.         ): Response
  273.     {
  274.         // a) les infobulles fusion de la page
  275.         // $lesdefs = array('ppi','mod','pro','eau','pfi','lis','mev');
  276.         $lesdefs = array('ppi','raf','mfp');
  277.         $deflog = array();
  278.         foreach($lesdefs as $ladef){
  279.             $deflog[$ladef] = $logdefservice->get_unedef($ladef); 
  280.         }
  281.         
  282.         // situation normale ras
  283.         return $this->render('security/nosoutils.html.twig', [
  284.             'deflog' => $deflog,
  285.         ]);
  286.     }
  287.     // Téléchargement du guide utilisateur
  288.     #[Route(path'/downloadguide'name'downloadguide')]
  289.     public function downloadguide(
  290.             Request $request
  291.             CsrfTokenManagerInterface $csrfTokenManager,
  292.             ParameterBagInterface $parambag,
  293.             DIVService $divservice,
  294.         ): Response
  295.     {
  296.         $cause = -1;
  297.         $ouv_poss false// protection ACL contre les lectures intempestives extérieures (saisie url directe)
  298.         
  299.         // begin token-guard --------------------------------------------------------------------------------------------------------------
  300.         if($request->query->get('dou')=='accueil'){
  301.               // pas de token
  302.         }else{
  303.             if($request->query->get('dou')=='autre'){
  304.                 $tokorigin 'yoplaboum';      // provenance de ailleurs
  305.             }
  306.             $csrfToken $request->query->get('tok');        // contient le _token
  307.             if (false === $csrfTokenManager->isTokenValid(new CsrfToken($tokorigin$csrfToken))) {
  308.                 $cause '4';
  309.                 // end token-guard --------------------------------------------------------------------------------------------------------------
  310.             }            
  311.         }
  312.         
  313.         if($cause==-1){        // poursuit
  314.             $data_nfid $request->query->get('nfid');   // nfid trafiqué
  315.             $gp $divservice->decrypt_cfppiid($data_nfid);
  316.             
  317.             if($gp!='57'){       // juste pour voir si accès direct pas détourné par des zombis
  318.                 $cause '2';      // pas ok
  319.             }else{
  320.                 $ouv_poss true;
  321.             }
  322.         }
  323.         if($ouv_poss){        // pour le moment pas d'accès au guide suprême, il est pas là
  324.             $nom_fichier 'guide_utilisateur_cf.pdf';
  325.             $chemin_fichier =  $parambag->get('dochelp_web_path');
  326.             $content file_get_contents($chemin_fichier.$nom_fichier);
  327.             $response = new Response();
  328.         
  329.             //set headers
  330.             $response->headers->set('Content-Type''mime/type');
  331.             // $response->headers->set('Content-Disposition', 'attachment;filename="'.bin2hex(random_bytes(32)).'.pdf"');
  332.             $response->headers->set('Content-Disposition''attachment;filename="guide_utilisateur_cf.pdf"');
  333.             $response->setContent($content);
  334.             return $response;
  335.             
  336.         }else{
  337.             $this->get('session')->getFlashBag()->add(
  338.                 'error',
  339.                 'Impossible d\'accéder à la fonction demandée'.' ('.$cause.')'
  340.             );
  341.             return $this->redirect($this->generateUrl('pageaccueil')); // renvoi caval
  342.         }
  343.     }
  344.     #[Route(path'/ruralconsult'name'ruralconsult')]
  345.     public function ruralconsult(): Response
  346.     {
  347.         return $this->render('security\ruralconsult.html.twig', array());        
  348.     }
  349.     #[Route(path'/logout'name'app_logout')]
  350.     public function logout(): void
  351.     {
  352.         throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  353.     }
  354. }