IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Authentification - Providers multiples et firewalls


Sujet :

Symfony PHP

  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 262
    Par défaut Authentification - Providers multiples et firewalls
    Bonjour,

    J'ai cherché sur la documentation de symfony (How to user multiple user providers) mais je pense faire des erreurs d'interprétation.

    j'aimerai savoir s'il était possible à partir d'un même formulaire de connexion de parcourir deux Entity différentes (ex : table User et table Player) pour authentifier et autoriser un utilisateur

    Code yaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    security:
        encoders:
            App\Entity\Player:
                algorithm: auto   
            App\Entity\User:
                algorithm: auto 
     
        # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
     
        providers:
     
            chain_provider:
                chain:
                    providers: [mon_provider_player, mon_provider_user]
     
            mon_provider_player :
                entity:
                    class: App\Entity\Player
                    property: emailPlayer   
     
            mon_provider_user :
                entity:
                    class: App\Entity\User
                    property: emailUser
     
        firewalls:
     
            dev:
                pattern: ^/(_(profiler|wdt)|css|images|js)/
                security: false
     
            player:
                anonymous: lazy
                provider: mon_provider_player
                form_login:
                     login_path: login 
                    check_path: login
                    csrf_token_generator: security.csrf.token_manager
                    success_handler: redirect.after.log
    ...
     
            user:
                anonymous: lazy
                provider: mon_provider_user
                form_login:
                    login_path: login 
                    check_path: login
                    csrf_token_generator: security.csrf.token_manager
                    success_handler: redirect.after.log
    .....

    lorsque je commente le "firewall - player" => le firewall parcourt la table USER et authentifie le USER sans pb.
    Inversement lorsque je commente le "firewall - user" => le firewall parcourt la table PLAYER et authentifie le PLAYER sans pb.

    C'est lorsque les 2 firewalls sont actifs (user et player) que l'authentification ne marche plus sur les 2 tables. Il ne parcourt que le table Player qui apparaît en premier dans le script.

    Avez-vous une solution pour parcourir 2 tables d'utilisateurs.

  2. #2
    Membre Expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Par défaut
    (Re)Bonjour,

    Pour parcourir deux tables, tu dois créer ton propre UserProvider.

    Dans ce UserProvider, tu code la recherche dans la première, puis dans la seconde table.

    Voici le paragraphe de la documentation qui te décrit comment créer ce user provider.

    https://symfony.com/doc/current/secu...-user-provider

    Je te recommande aussi d'installer le makerBundle qui peut te créer le "patron", le "modèle" de plein de classe, dont le UserProvider. Ca t'évite de coder manuellement beaucoup de choses et cela te permet de suivre les bonnes pratiques de Symfony.

    Alexandre
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

  3. #3
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 262
    Par défaut
    merciiii

    je vais essayer tout de suite

  4. #4
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 262
    Par défaut
    j'ai lu toute la documentation mais il y a des points qui m'échappent....

    J'ai bien une class User implements UserInterface.

    si j'ai bien compris, je dois passer par la classe UserProvider implements UserProviderInterface pour parcourir deux tables.

    Cette classe comporte 3 méthodes :
    loadUserByUsername($username)
    refreshUser(UserInterface $user)
    supportClass

    Je suppose que je dois coder ma recherche dans loadUserByUsername

    Mais je ne comprend pas la logique sous-jaccente.

    Cette classe vient-elle en complément de la classe User ou bien la remplace t'elle. J'ai cherché des tuto sur l'authentification à partir de deux tables mais rien du tout

    concernant le codage faut-il que j'utilise le UserRepository pour faire ma requête

    Auriez-vous un exemple concret pour m'aider

  5. #5
    Membre Expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Par défaut
    Bonjour,

    Je te recommande les tutoriels de SymfonyCast. Ils sont pas mal.

    Tu as compris, c'est bien la méthode loadByUsername qui va nous servir.

    Pour retrouver ton utilisateur, tu dois le retrouver dans deux tables : User et Player si j'ai bien suivi. Tu as donc deux dépôts : UserRepository et PlayerRepository. Admettons que tu cherches à les retrouver par leur email, ta méthode va ressembler à cela :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
        public function loadUserByUsername($username)
        {
            // On cherche l'utilisateur dans la table player
            $player = $this->playerRepository->findByEmail($username);
     
            //On vérifie qu'on a qqchose :
            if ($player instanceof Player) {
               return $player; //Bien sûr il faut que Player implémente UserInterface
            }
     
            //Si on est ici, c'est qu'on ne l'a pas trouvé. On cherche dans la table
            // On cherche l'utilisateur dans la table user
            $user = $this->userRepository->findByEmail($username);
     
            //On vérifie qu'on a qqchose :
            if ($user instanceof User) {
               return $player; //Bien sûr il faut que Player implémente UserInterface
            }
     
            //Bon bah ce n'est ni un user, ni un player, je génère une exception de type UsernameNotFoundException (c'est une erreur dans la doc de générer une simple Exception!)
            throw new UsernameNotFoundException('TODO: fill in loadUserByUsername() inside '.__FILE__);
        }
    Le problème, c'est que playerRepository et userRepository sont des propriétés non déclarées pour le moment. Eh bien avec Symfony, tu dois toujours réfléchir selon le patron de conception de l'injection de dépendance. On va injecter ces objets dans notre UserProvider. Et tu vas voir, c'est super facile :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        private $userRepository ;
        private $playerRepository;
     
        /**
         * Dans les paramètres j'injecte par dépendance l'entitéManagerInterface
         */
        public function __construct(EntityManagerInterface $entityManager)
        {
            //L'injection de dépendance c'est occupée de bien initialiser $entityManager.
            $this->userRepository = $entityManager->getRepository(User::class);
            $this->playerRepository = $entityManager->getRepository(Player::class);
        }
    Je ne sais plus si c'est à partir de Symfony 4 ou 5, mais en Sf5, tu peux passer directement les deux Repository dans les arguments du contrôleurs pour éviter de passer par l'entitymanager, mais c'est du détail
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

  6. #6
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2015
    Messages
    262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2015
    Messages : 262
    Par défaut
    Je pensais avoir compris mais je pense que j'ai un problème de dépendances car malgré le fait que j'ai créé mes 2 méthodes findByEmail($username) dans UserRepository et PlayerRepository, il n'arrive pas à les trouver....

    Si j'ai bien compris, on déclare deux propriétés et à l'aide du constructeur on leur affecte l'entityManager et va chercherle repository respectif.
    (très joli).

    Puis on n'a plus qu'à déclarer la méthode que l'on veut (içi => findByEmail);

    Cependant, dans la méthode loadUserByUsername, j'ai une erreur sur la méthode (non définie)...

    voici mon code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    ....
    class UserProvider implements UserProviderInterface
    {
        private $userRepository;
        private $playerRepository;
    
        public function __construct(EntityManagerInterface $entityManager)
        {
            $this->userRepository = $entityManager->getRepository(User::class);
            $this->playerRepository = $entityManager->getRepository(Player::class);
        }
    
        /**
         *
         * @return UserInterface
         *
         * @throws UsernameNotFoundException if the user is not found
         */
        public function loadUserByUsername($username)
        {
            $player = $this->playerRepository->findByEmail($username); // méthode non définie
    
             if ($player instanceof Player) {
                return $player; 
            }
    
            $user = $this->userRepository->findByEmail($username);  // méthode non définie
    
            if ($user instanceof User) {
                return $player; 
            }
            throw new \Exception('TODO: fill in loadUserByUsername() inside ' . __FILE__);
        }
    j'ai essayé de faire :

    use App\Repository\UserRepository;
    use App\Repository\PlayerRepository;

    et d'injecter directement les dépendances dans la méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     public function loadUserByUsername($username, UserRepository $userRepository, PlayerRepository $playerRepository) {
     
            $player = playerRepository->findByEmail($username);
    Mais j'ai un gros message d'erreur lié à la sécurité

  7. #7
    Membre Expert
    Avatar de Alexandre T
    Homme Profil pro
    Chef de projets AMO
    Inscrit en
    Mai 2002
    Messages
    1 213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projets AMO
    Secteur : Transports

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 213
    Par défaut
    Citation Envoyé par bricoreur Voir le message
    Cependant, dans la méthode loadUserByUsername, j'ai une erreur sur la méthode (non définie)...
    Bonjour,


    • Quel est le contenu de la $username?
    • Comment recherches-tu un utilisateur (par son mail, son nom?) ?
    • Quel est la colonne (mail/email/username ?) dans chacune de tes tables Player et User ?


    Je te pose ses questions, car en raison de ton message d'erreur je pense que dans le PlayerRepository, comme dans le UserRepository, tu n'as pas de méthode findByEmail.

    Tu as deux options :
    • la créer ;
    • l'invoquer par magie : par défaut s'il y a une colonne toto dans ta table, la méthode findByToto est automatiquement/magiquement créée à la volée.


    Le code d'une telle méthode est en général qqchose de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public function findByEmail($email) 
    {
        return $this->findBy([
            'email' => $email
        ]);
    }
    Désolé, je suis débordé, je n'ai pas le temps de tester que la syntaxe est exacte, mais tu as l'idée.
    Alexandre Tranchant
    Chef de projet AMO pour le Cerema.
    Retrouvez mes articles sur PHP et Symfony

Discussions similaires

  1. [[sharepoint]] authentification multiple
    Par ragkiki dans le forum Configuration
    Réponses: 0
    Dernier message: 09/09/2009, 08h18
  2. [[sharepoint]] authentification multiple
    Par ragkiki dans le forum SharePoint
    Réponses: 0
    Dernier message: 09/09/2009, 08h18
  3. Authentification multiple sous WebLogic (Portal) 10
    Par cclermont dans le forum Weblogic
    Réponses: 0
    Dernier message: 08/12/2008, 16h47
  4. Authentification LDAP multiple
    Par McFoggy dans le forum Apache
    Réponses: 1
    Dernier message: 06/06/2008, 13h58
  5. Réponses: 7
    Dernier message: 22/08/2007, 09h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo