In my little project I want a user imediadly log out if the user was banned (By Admin or by changing the Database with a tool). I tried to set a cookie with symfony but it dosen’t work. But if I use vanilla PHP for this solution it works as requested.
For this I use an eventlistener named “UserStatusListener.php” and in my LoginController I have a function to handle the logout-message (The reason why the user was logged out).
Maybe one of you find the issue. I want to use the Framework instead of vanilla PHP.
Here my EventListener:
<?php
// src/EventListener/UserStatusListener.php
namespace AppEventListener;
namespace AppEventListener;
use AppRepositoryUserRepository;
use SymfonyComponentHttpFoundationCookie;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpKernelEventRequestEvent;
use SymfonyComponentRoutingRouterInterface;
use SymfonyBundleSecurityBundleSecurity;
use SymfonyComponentHttpFoundationResponse;
class UserStatusListener
{
private $userRepository;
private $security;
private $router;
public function __construct(UserRepository $userRepository, Security $security, RouterInterface $router)
{
$this->userRepository = $userRepository;
$this->security = $security;
$this->router = $router;
}
public function onKernelRequest(RequestEvent $event): void
{
$user = $this->security->getUser();
if ($user) {
$updatedUser = $this->userRepository->find($user->getId());
if ($updatedUser && $updatedUser->getBannedUntil() !== null) {
$now = new DateTime();
if ($now < $updatedUser->getBannedUntil()) {
// Setze ein Cookie mit der Benutzer-ID
// $cookie = new Cookie('banned_user_id', $user->getId(), time() + 3600, '/', 'stage.hhb.kighlander.de', true); // 1 Stunde gültig
setcookie('banned_user_id', $user->getId(), time() + 3600, '/', '.kighlander.de', true);
// Erstelle eine neue Response, wenn keine vorhanden ist
if (!$event->getResponse()) {
$event->setResponse(new Response());
}
// Setze das Cookie in die Response-Header
// $event->getResponse()->headers->setCookie($cookie);
// Benutzer ausloggen und zur Logout-Methode weiterleiten
$event->setResponse(new RedirectResponse($this->router->generate('app_logout')));
return; // Beende die Methode hier
}
}
}
}
}
And here my LoginController:
<?php
// src/Controller/LoginController.php
namespace AppController;
use AppRepositoryUserRepository;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationRequestStack;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAttributeRoute;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
class LoginController extends AbstractController
{
private $requestStack;
private $userRepository;
public function __construct(RequestStack $requestStack, UserRepository $userRepository)
{
$this->requestStack = $requestStack;
$this->userRepository = $userRepository;
}
#[Route('/login', name: 'app_login')]
public function index(
AuthenticationUtils $utils
): Response
{
$lastUsername = $utils->getLastUsername();
$error = $utils->getLastAuthenticationError();
return $this->render('login/index.html.twig', [
'lastUsername' => $lastUsername,
'error' => $error
]);
}
#[Route('/logout', name: 'app_logout')]
public function logout()
{
}
#[Route('/logout_message', name: 'app_logout_message')]
public function logoutMessage(): Response
{
// $bannedUserId = $this->requestStack->getCurrentRequest()->cookies->get('banned_user_id');
$bannedUserId = $_COOKIE['banned_user_id'] ?? null;
if ($bannedUserId) {
// Benutzer aus der Datenbank abrufen
$user = $this->userRepository->find($bannedUserId);
if ($user && $user->getBannedUntil() !== null) {
$now = new DateTime();
if ($now < $user->getBannedUntil()) {
// Setze eine Warnung für den gebannten Benutzer
$this->addFlash('warning', 'Du bist gebannt. Bitte kontaktiere den Support.');
}
}
// Lösche das Cookie
$response = $this->redirectToRoute('app_micro_post');
$response->headers->clearCookie('banned_user_id');
return $response;
} else {
// Setze die Erfolgsnachricht für den normalen Logout
$this->addFlash('success', 'Du hast Dich erfolgreich ausgeloggt.');
}
return $this->redirectToRoute('app_micro_post');
}
}
At least a part of “service.yaml” for registration the EventListener
services:
AppEventListenerUserStatusListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
I outcomment the framework-version and the implemented vanilla-version works.
Thank you 😉
To test the code I created a test-user, logged in (without a ban), change to phpmyadmin and set a ban_until one day in future, change to the logged in user, make a click to an other part of the app and I was logged out with the “normal” logout-message.
After I made the changes to vanilla php I got the correct logout message “Du bist gebannt. Bitte kontaktiere den Support” (Sorry, my site is in german 😉 )