L3 Info : PHP et Applications Web
 
◃  Ch. 13 Symfony 7.4  ▹
 

Authentification dans Symfony 7.4

  • Mots-clés :
Terme Description
Utilisateur Entité représentant un compte (ex: User).
Provider Fournit les données de l’utilisateur (ex: EntityUserProvider).
Firewall Zone de sécurité définissant comment l’utilisateur s’authentifie.
Authenticator Classe personnalisable pour gérer le processus d’authentification.
Role Permission associée à un utilisateur (ex: ROLE_ADMIN).
Token Objet représentant l’état d’authentification de l’utilisateur.
  • Mise en place de l’authentification par formulaire :

    • Installation des dépendances

      composer require symfony/security-bundle
      composer require symfony/maker-bundle --dev  # Pour générer du code rapidement
    • Création de l’entité User, Symfony fournit une commande pour générer une entité User avec les champs nécessaires :

      php bin/console make:user
    • Exemple de code généré :

      // src/Entity/User.php
      use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
      use Symfony\Component\Security\Core\User\UserInterface;
      
      class User implements UserInterface, PasswordAuthenticatedUserInterface
      {
      private ?int $id = null;
      private string $email;
      private array $roles = [];
      private string $password;
      
        // Getters/Setters...
        public function getUserIdentifier(): string { return $this->email; }
        public function getRoles(): array { return $this->roles; }
        public function getPassword(): string { return $this->password; }
        public function eraseCredentials() {}
      }
    • Configuration de la sécurité (Fichier config/packages/security.yaml) :

      security:
      enable_authenticator_manager: true
      password_hashers:
      Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
      providers:
      app_user_provider:
          entity:
              class: App\Entity\User
              property: email
      firewalls:
      main:
          lazy: true
          provider: app_user_provider
          form_login:
              login_path: app_login
              check_path: app_login
          logout:
              path: app_logout
    • Création du formulaire de login Contrôleur

      php bin/console make:controller Login

      Exemple de contrôleur généré :

      // src/Controller/LoginController.php
      class LoginController extends AbstractController
      {
      #[Route('/login', name: 'app_login')]
      public function login(AuthenticationUtils $authenticationUtils): Response
      {
      $error = $authenticationUtils->getLastAuthenticationError();
      $lastUsername = $authenticationUtils->getLastUsername();
      
      return $this->render('login/index.html.twig', [
          'last_username' => $lastUsername,
          'error' => $error
      ]);
      }
      #[Route('/logout', name: 'app_logout')]
      public function logout(): void {}
      }

      Vue Twig (templates/login/index.html.twig)

      <form method="post">
      <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
      <label for="inputEmail">Email</label>
      <input type="email" id="inputEmail" name="email" value="{{ last_username }}" autofocus>
      <label for="inputPassword">Mot de passe</label>
      <input type="password" id="inputPassword" name="password">
      <button type="submit">Se connecter</button>
      </form>
  • Gestion des mots de passe

    • Hashage automatique Symfony hache automatiquement les mots de passe grâce à password_hashers dans security.yaml.
    • Pour hacher un mot de passe manuellement (ex: lors de l’inscription) :
      // Dans un contrôleur ou un service
      $user->setPassword(
      $passwordHasher->hashPassword($user, $plainPassword)
      );
    • Inscription d’un utilisateur Exemple de contrôleur pour l’inscription :

      #[Route('/register', name: 'app_register')]
      public function register(Request $request, UserPasswordHasherInterface $passwordHasher): Response
      {
      $user = new User();
      $form = $this->createForm(RegistrationFormType::class, $user);
      $form->handleRequest($request);
      if ($form->isSubmitted() && $form->isValid()) {
          $user->setPassword(
              $passwordHasher->hashPassword($user, $form->get('plainPassword')->getData())
          );
          $entityManager->persist($user);
          $entityManager->flush();
          return $this->redirectToRoute('app_login');
      }
      
      return $this->render('registration/register.html.twig', [
          'registrationForm' => $form->createView(),
      ]);
      }
  • Protection des routes

    • Restriction d’accès Dans security.yaml, définissez les règles d’accès :
      access_control:
         - { path: ^/admin, roles: ROLE_ADMIN }
         - { path: ^/profile, roles: ROLE_USER }
    • Vérification dans les contrôleurs
      #[Route('/profile', name: 'app_profile')]
      public function profile(): Response
      {
      $this->denyAccessUnlessGranted('ROLE_USER');
      // ...
      }
  • Authentification avancée

    • Authentification par API (JSON) Utilisez un Authenticator personnalisé pour gérer les requêtes API :

      php bin/console make:auth

      Exemple de code pour un authentificateur API :

      // src/Security/LoginFormAuthenticator.php
      class LoginFormAuthenticator extends AbstractAuthenticator
      {
      public function supports(Request $request): ?bool
      {
      return $request->headers->has('X-AUTH-TOKEN');
      }
      
      public function authenticate(Request $request): Passport
      {
          $token = $request->headers->get('X-AUTH-TOKEN');
          // Logique de validation du token...
      }
      
      public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
      {
          return null; // Laisse Symfony continuer
      }
      
      public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
      {
          return new JsonResponse(['error' => $exception->getMessage()], 401);
      }
      }
  • Conseils de base :

    • Ne jamais stocker les mots de passe en clair : Toujours utiliser le hashage.
    • Protéger contre les attaques CSRF : Utilisez les tokens CSRF dans les formulaires.
    • Limiter les tentatives de connexion : Implémentez un système de rate limiting.
    • Utiliser HTTPS : Pour sécuriser les échanges.
    • Gérer les rôles avec parcimonie : Évitez de multiplier les rôles inutiles.
  • Ressources