<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Validator\Validator\ValidatorInterface; // contrôleur de contraintes
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; // l'encodeur ofcourse
use App\Service\LOGDEFService;
use App\Entity\usr;
use App\Entity\usl;
class SecurityController extends AbstractController
{
#[Route(path: '/identification', name: 'identification')]
public function identification
(
ManagerRegistry $doctrine,
AuthenticationUtils $authenticationUtils,
UserPasswordHasherInterface $passwordHasher,
): Response
{
$em = $doctrine->getManager();
// activer si besoin de coder / définir un pwd pour un glups
/*
$usr = $em->getRepository(usr::class)->findOneBy(array('username'=>'stephy.deveaux'));
$plaintextPassword = 'agagagagag:';
$hashedPassword = $passwordHasher->hashPassword(
$usr,
$plaintextPassword
);
$usr->setPassword($hashedPassword);
$em->persist($usr);
$em->flush();
*/
// =============== CTRL LOGIN'S =====================
//var_dump($_SERVER);
// vérif occurences demandes : combien de fois en combien de temps pour quel login
$delaymin = 1800; // délai maxi pour une série de tentative de login pour une IP (30')
$nbtryipmax = 16; // nb tentatives max pour une même IP en moins de 'delaymin'
$nbtrylogmax = 10; // nb tentatives échouées max pour un login en moins de 'delaymin'
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ // récup IP origine dde
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$datnow = time();
$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)));
$datlimit = $datnow - $delaymin;
$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)));
// 1° niveau CTRL : affichage répété page login pour rien ================================
$ctx = '';$nbtry=0;
if((isset($_SERVER['HTTP_REFERER'])) && (isset($_SERVER['HTTP_COOKIE']))){ // logout possible, pas de vérif
$ctx = 'logout';
// dd('http referer isset et cookie');
}
// nb ddes pour cette IP dans les dernières 'delaymin' secondes avec ou sans login
if($ctx!='logout'){
// dd($ctx.', '.$ip);
$query = $em->getRepository(usl::class)->createQueryBuilder('usl')
->select("COUNT(usl.uslip) AS nbtry")
->where('usl.uslip = :uslip')
->setParameter('uslip', $ip)
->andwhere('usl.uslip NOT IN (:iplocale)')
// ->setParameter('iplocale' , array('127.0.0.1','192.168.26.50')) // pour audit cq + locloc
->setParameter('iplocale' , array('127.0.0.1')) // locloc ou cq
->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
->setParameter('perioddde' ,$perioddde)
->setParameter('periodlimit' ,$periodlimit)
;
$nbtry = $query->getQuery()->getSingleScalarResult();
}
// 1° blocage : affichage excessif de la page de login pour rien
if($nbtry>=$nbtryipmax){ // abus
$this->addFlash('Erreur', "IP Reconnectez-vous dans 1 heure. Tentatives de connexion excessives : ".$nbtryipmax);
// renvoi page erreur
return $this->render('security/erreur.html.twig',
array(
'ip' => $ip
)
);
}
// 2° niveau CTRL : tentative de login répétée avec échec => error ========================
// vérif si même IP a tenté de se loguer plus de nbtrylogmax pour un login avec N comptes....
$query = $em->getRepository(USL::class)->createQueryBuilder('usl')
->select("COUNT(usl.uslip) AS nbtry")
->where('usl.uslctx =:uslctx')
->setParameter('uslctx', 'error')
->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
->setParameter('perioddde' ,$perioddde)
->setParameter('periodlimit' ,$periodlimit)
;
$nbtry = $query->getQuery()->getSingleScalarResult();
if($nbtry>=$nbtrylogmax){ // abus
$this->addFlash('Erreur', "IP Reconnectez-vous dans 1 heure. Tentatives de connexion excessives : ".$nbtrylogmax);
// renvoi page erreur
return $this->render('security/erreur.html.twig',
array(
'ip' => $ip
)
);
}else{
// enregistrement des caractéristiques de la demande de login
$error = $authenticationUtils->getLastAuthenticationError(); // get the login error if there is one
$lastUsername = $authenticationUtils->getLastUsername(); // last username entered by the user
// possible provenance logout, récup phpsessid pour id usr
$cook = '';
if(isset($_SERVER['HTTP_REFERER'])){
if(isset($_SERVER['HTTP_COOKIE'])){ // id usr possibl
$cook = str_replace('PHPSESSID=','',$_SERVER['HTTP_COOKIE']);
$pos = strpos($cook, ";");
if(($pos>1)&&($pos<255)){
$cook = substr($cook, 0, $pos-1);
}else{
$cook = substr($cook, 0, 254);
}
}
}
if($error){ // inactive renvoi erreur niveau Render (ci-dessous)
$login = $lastUsername;
$ctx = 'error';
$this->addFlash('Erreur', 'Identification invalide');
}else{
if($lastUsername!=''){
$login = $lastUsername;
$ctx = 'login';
if($cook==''){
$ctx = 'start';
}
}else{
$login = '';
if($cook==''){
$ctx = 'start';
}else{
$ctx = 'logout';
}
}
}
// enrgt dde : IP + Heure + login (0,1)
$datdde = new \DateTime();
$usl = new usl;
$usl->setUslip($ip);
$usl->setUsldat($datdde);
$usl->setUsllogin($login);
$usl->setUslctx($ctx);
$usl->setUslcook($cook);
$em->persist($usl);
$em->flush();
// 2° niveau vérif ================================
// nb échecs pour ce login dans les dernières 'delaymin' secondes
$nbtry = 0;
if($login!=''){
$query = $em->getRepository(USL::class)->createQueryBuilder('usl')
->select("COUNT(usl.uslip) AS nbtry")
->where('usl.usllogin = :usllogin')
->setParameter('usllogin', $login)
->andwhere('usl.uslctx <> :uslctx')
->setParameter('uslctx', 'error')
->andwhere('usl.usldat BETWEEN :periodlimit AND :perioddde')
->setParameter('perioddde' ,$perioddde)
->setParameter('periodlimit' ,$periodlimit)
;
$nbtry = $query->getQuery()->getSingleScalarResult();
}
if($nbtry>=$nbtrylogmax){
$this->addFlash('Erreur', "LOGIN : Reconnectez-vous dans 1 heure, nb tentatives excessives > ".$nbtrylogmax);
// renvoi page erreur
return $this->render('security/erreur.html.twig',
array(
'ip' => $ip
)
);
}else{
// situation normale ras
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
// 'deflog' => $deflog,
]);
}
}
}
#[Route(path: '/login', name: 'app_login')]
public function login
(
AuthenticationUtils $authenticationUtils,
LOGDEFService $logdefservice,
): Response
{
// en cas d'erreur, enregistrement des caractéristiques de la demande de login
// TODO : tenter de réafficher identification !?
$error = $authenticationUtils->getLastAuthenticationError(); // get the login error if there is one
$lastUsername = $authenticationUtils->getLastUsername(); // last username entered by the user
// ACCUEIL : possible provenance logout, récup phpsessid pour id usr
$cook = '';
if(isset($_SERVER['HTTP_REFERER'])){
if(isset($_SERVER['HTTP_COOKIE'])){ // id usr possibl
$cook = str_replace('PHPSESSID=','',$_SERVER['HTTP_COOKIE']);
$pos = strpos($cook, ";");
if(($pos>1)&&($pos<255)){
$cook = substr($cook, 0, $pos-1);
}else{
$cook = substr($cook, 0, 254);
}
}
}
if($error){ // inactive renvoi erreur niveau Render (ci-dessous)
$login = $lastUsername;
$ctx = 'error';
$this->addFlash('Erreur', 'Identification invalide');
}else{
if($lastUsername!=''){
$login = $lastUsername;
$ctx = 'login';
if($cook==''){
$ctx = 'start';
}
}else{
$login = '';
if($cook==''){
$ctx = 'start';
}else{
$ctx = 'logout';
}
}
}
// NOS OUTILS : les infobulles fusion de la page
$lesdefs = array('ppi','raf','pro','mfp');
$deflog = array();
foreach($lesdefs as $ladef){
$deflog[$ladef] = $logdefservice->get_unedef($ladef);
}
return $this->render('security\accueil.html.twig', array(
'last_username' => $lastUsername,
'deflog' => $deflog,
'error' => $error
)
);
}
// les cartes à jouer avec les outils financiers
#[Route(path: '/nosoutils', name: 'nosoutils')]
public function nosoutils(
LOGDEFService $logdefservice,
): Response
{
// a) les infobulles fusion de la page
// $lesdefs = array('ppi','mod','pro','eau','pfi','lis','mev');
$lesdefs = array('ppi','raf','pro','mfp');
$deflog = array();
foreach($lesdefs as $ladef){
$deflog[$ladef] = $logdefservice->get_unedef($ladef);
}
// situation normale ras
return $this->render('security/nosoutils.html.twig', [
'deflog' => $deflog,
]);
}
#[Route(path: '/ruralconsult', name: 'ruralconsult')]
public function ruralconsult(): Response
{
return $this->render('security\ruralconsult.html.twig', array());
}
#[Route(path: '/logout', name: 'app_logout')]
public function logout(): void
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}