Bonjour,
Quelqu'un pourrais m'aider à trouver une solution à mon problème?
En effet, cela fait maintenant deux jours que je cherche sur le net une solution à ma préoccupation.
Je souhaiterais enregistrer l'heure de connexion et deconnexion de chaque utilisateur dans ma base de données
J'ai fait des recherches mais je ne trouve pas.
J'utilise Symfony 5

5 réponses


Il faut utiliser les évènements utilisé par le composant security (documente toi sur les "event subscriber" sur Symfony)

pour la connexion au moment tu login tu enregistres, pour la deconnexion, bcp plus compliqué d'avoir une exactitude, tu peux essayer de detourner les SSE (server sent events), ta page reste connectée a ton serveur, etl lorsqu'il y a deconnexion tu l'enregistres a son tour ou un simple ping ajax toutes les X secondes qui fait enregistrer au serveur le dernier et si plus de 3 ou 4 fois la periode d'envoi tu le considere comme deconnecté

Merci pour votre reponse, j'ai pu mettre en place grâce au event subscriber l'heure de la connexion de chaque utilisateur dans ma base de données
Lorsque la connexion se passe bien, j'enregistre dans la table user_session, la date et l'heure de connexion et l'identifiant de l'utilisateur qui se connecte.
A la deconnexion, je passe par LogoutListener, pour recuperer l'utilisateur qui se déconnecte, et pouvoir mettre à jour la table user_session, en remplissant le champ fin_connexion.
Mon soucis c'est la modification de la ligne qui avait été crééé lors de la connexion. J'arrive à recupérer la ligne qui doit être modifiée mais comment modifier la ligne que je n'arrive pas.
Veuillez m'aider à modifier la ligne en ajoutant la date et l'heure de deconnexion.
voici le code ci-dessous :
.../src/EventSubscriber/LogoutListener.php
<?php

namespace App\EventSubscriber;

use App\Entity\User;
use App\Entity\CsmSessionUtilisateur;

use App\Form\CsmSessionUtilisateurType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Form\FormBuilderInterface;
use App\Repository\CsmSessionUtilisateurRepository;
use Symfony\Component\Security\Http\Event\LogoutEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Forms;

class LogoutListener implements EventSubscriberInterface
{
private $entityManager;
protected $requestStack;
//protected $request;

public function __construct(EntityManagerInterface $manager, RequestStack $requestStack/*, request $request*/)
{
    $this->entityManager = $manager;
    $this->requestStack = $requestStack;
    //$this->request = $request;
}

public function onLogout(LogoutEvent $logoutEvent): void
{

    $Token = $logoutEvent->getToken();
    $user = $Token->getUser();
    $SUR_FIN = new \DateTime();
    $SessionUtilisateur = new CsmSessionUtilisateur();
    //Recuperation de la ligne à modifier en ajoutant la date fin connexion
    $Repository = $this->entityManager->getRepository(CsmSessionUtilisateur::class);  
    $verification = $Repository->verify($user->getId());

    $SessionUtilisateur->setSURFIN($SUR_FIN)
    /*->setSURUSER($verification[0]->getSURUSER())
    ->setSURCOMMENTAIRE($verification[0]->getSURCOMMENTAIRE())
    ->setSURDEBUT($verification[0]->getSURDEBUT())*/
    ;
    $this->entityManager->persist($SessionUtilisateur);
    $this->entityManager->flush();
}

public static function getSubscribedEvents(): array
{
    return [
        LogoutEvent::class => 'onLogout',
    ];
}

}

lors de la connexion tu crees ta nouvelle entree dans user_session et tu enregistre l'id en session. dans le logoutlistener tu peux ainsi lire la session, recup la ligne et la mettre a jour, par contre comme grafikart te disait sur ton autre post, la ca va fonctionner quand l'utilisateur va cliquer sur 'se deconnecter' si il laisse sa session "mourrir" et devient ainsi deconnecté le listener n'est pas appellé.

Hello :)

Alors pour la session, tu as deux solutions:

  • Soit tu part du principe que l'utilisateur reste connecté jusqu'à ce qu'il se déconnecte, dans ce cas au lieux d'utiliser une session tu utilises un cookie

  • Soit tu utilises la session, dans ce cas il faudrait que le fait qu'une personne quitte le site ce soit considéré comme une deconexion, tu fait un event beforeunload qui tape une API qui marque la personne comme déconectée

Si tu ne veux pas considérer une personne qui quitte la page comme deconnectée, il y a une autre solution, tu traques toujours le fait qu'une personne quitte le site, mais tu dois aussi traquer quand il arrive dans le site, dans les données traquées tu enregistre l'identifiant de la session de connexion aussi, ensuite tu fais un cron qui récupère toutes les perssones qui ne sont pas présents dans le site, tu vérifies si leur session est expirée, si oui tu lances un event deconnexion sur la personne

Pour le traquing de session expirée, tu utilises l'event qui trackes si un utilisateur quitte la page pour enregistrer en base à quelle heure la session est expirée, et il faut aussi un event quand l'utilisateur retourne sur la page, si il possède une session tu vires l'heure d'expiration de la session

Dans l'idée ce serait

windows.addEventListenner("load", () => {
    if (!sessionStorage.getItem("presence") && sessionStorage.getItem("login")) { // la condition c'est pour éviter de lancer la requete API à chaque fois que l'utilisateur se balade sur le site, et aussi pour éviter de lancer l'api pour les utilisateurs qui ne sont pas connecté ^^
        $api->post("/api/set_user_session", { session_expired_at: null })
            .then(() => sessionStorage.setItem("presence", true))
    }
})

windows.addEventListenner("beforeunload", () => {
        $api->post("/api/set_user_session", { session_expired_at: sessionStorage.getItem("login").expired_at })
            .then(() => sessionStorage.setItem("presence", false))
})

Et pour le cron

    $users = "select * from users where presence = false and session_expired_at > NOW() and session_expired_at is not null" // A faire en mode Symfony, et si des données se trouve dans une autre table ajoutes les jointures

    $users->each(funtion (User $user) {
        $user->last_logout_at = $user->session_expired_at;
        $user->save();
    })

Bon j'ai fais à l'aveugle après faut que tu adaptes avec tes variables noms de table et pouur que ça fonctionne ^^