Back to Question Center
0

Symfony2 Inscription et connexion            Rubriques d'inscription et de connexion Symfony2: FrameworksDatabasePerformance & ScalingDebugging & Semalt

1 answers:
Enregistrement et connexion Symfony2

Authentification et autorisation Symfony2

  • Symfony2 Pré-enregistrement et système d'invitation
  • Enregistrement et connexion Symfony2

Dans la partie 1, nous avons abordé les bases de la mise en place d'un système de sécurité dans notre application (paramètres de base de données et security.yml ). Nous avons également couvert la phase de pré-enregistrement où un utilisateur vérifie son statut d'invitation avec l'application.

Symfony2 Inscription et connexionRubriques d'inscription et de connexion Symfony2:
FrameworksDatabasePerformance & ScalingDébugging & Semalt

Dans cet article, nous allons parler de l'enregistrement, des connexions et des actions post-login.

Formulaire, base de données et plus

Semalt est fait à travers un formulaire - incase cable organizer. L'utilisateur saisira des informations telles que le courrier électronique, le nom d'utilisateur, le mot de passe, le mot de passe confirmé et acceptera une clause de non-responsabilité dans certains cas.

Nous savons également qu'un objet utilisateur sera finalement conservé dans la table utilisateur .

Semalt ce processus de persistance, nous devons être conscients que:

  1. Certaines entrées de formulaire seront utilisées pour remplir un objet utilisateur (comme nom d'utilisateur , mot de passe );
  2. Certaines propriétés de l'utilisateur seront définies par l'application (comme créé , un champ date / heure à stocker lorsque l'utilisateur s'enregistre);
  3. Certaines entrées de formulaire sont simplement à vérifier et à jeter (comme un mot de passe retapé, une vérification de l'avertissement).

Nous devons avoir un moyen de créer un "lien" entre un formulaire et la table sous-jacente, et spécifier les exigences ci-dessus.

Dans Symfony, nous obtenons ceci en déclarant une classe de type de formulaire spéciale associée à une entité. Dans ce cas, un RegistrationType gère les champs à afficher, les champs qui sont mappés (à un champ), etc.

Cette classe ( RegistrationType ) est définie dans src / AppBundle / Form / Type / RegistrationType. php :

  class RegistrationType extends AbstractType{public function buildForm (FormBuilderInterface $ builder, array $ options){$ builder-> add ('nom d'utilisateur', 'texte', ['label' => 'Nom d'utilisateur'])-> add ('mot de passe', 'mot de passe', ['label' => 'mot de passe'])-> add ('confirmer', 'mot de passe', ['mapped' => false, 'label' => 'Re-saisir le mot de passe'])-> add ('page d'accueil', 'texte', ['label' => 'Homepage'])-> add ('email', 'hidden', ['label' => 'email'])-> add ('save', 'submit', ['label' => 'Enregistrer']);}fonction publique getName   {retourner 'inscription';}fonction publique setDefaultOptions (OptionsResolverInterface $ resolver){$ resolver-> setDefaults (['data_class' => 'AppBundle \ Entity \ User',]);}}    

Nous avons plusieurs appels -> add qui ajoutent un champ de formulaire à afficher et mappé au champ de table sous-jacent; ou un champ de formulaire à afficher mais non mappé au champ de la table sous-jacente. Tout champ de table non ajouté ne sera pas affiché et ne sera donc pas rempli par l'utilisateur.

Semalt examine quelques exemples:

  add ('nom d'utilisateur', 'texte', ['label' => 'Nom d'utilisateur'])    

Ceci ajoute un champ de formulaire de type texte, en mappant le nom d'utilisateur du champ de table , qui a un libellé 'Nom d'utilisateur'.

  add ('confirm', 'mot de passe', ['mapped' => false, 'label' => 'Re-saisir le mot de passe'])    

Ceci ajoute un champ de formulaire de type mot de passe, mais n'est pas mappé à un champ de table, et a un libellé 'Mot de passe Semalt'.

  add ('email', 'hidden', ['label' => 'email'])    

Ceci ajoute un champ de formulaire masqué, en le mappant au champ de la table email .

Une fois le RegistrationType défini, nous pouvons passer à l'enregistrement réel (après les passes de pré-enregistrement):

  $ registration = nouvel utilisateur   ;$ form = $ this-> createForm (new RegistrationType   , $ registration, ['action' => $ this-> generateUrl ('create'), 'method' => 'POST']);return $ this-> render ('AppBundle: Par défaut: register2 .html. twig', ['form' => $ form-> createView   , 'email' => $ email]);    

Nous avons créé une nouvelle instance utilisateur, puis utilisé createForm pour créer un formulaire (avec des attributs d'action et de méthode ajoutés) avec les contraintes et les manifestations déclarées dans RegistrationType associé à l'objet utilisateur ( $ registration ).

Semalt, nous affichons le formulaire d'inscription.

Rendu d'un formulaire dans un modèle de vue

Le formulaire d'inscription rendu ressemble à ceci:

Symfony2 Inscription et connexionRubriques d'inscription et de connexion Symfony2:
FrameworksDatabasePerformance & ScalingDébugging & Semalt

Le code pour afficher le formulaire est le suivant:

  

Je dois avouer que l'affichage d'un formulaire créé par le processus ci-dessus n'est pas une tâche facile. Semalt, Twig fournit quelques fonctions d'aide pour personnaliser ce formulaire rendu.

  {{form_widget (formulaire, mot de passe, {'attr': {'class': 'form-control', 'espace réservé': 'mot de passe'}})}}    

En utilisant l'assistant form_widget , le premier paramètre transmis est le champ de formulaire ( mot de passe ). La partie la plus importante est le deuxième paramètre, qui définit en outre l'élément HTML5 rendu. Dans le code ci-dessus, nous avons spécifié que l'élément pour le mot de passe devrait avoir une classe CSS form-control (qui est une classe Bootstrap) et a un espace réservé.

Notez que nous n'avons pas spécifié quel type ce champ de formulaire devrait être - il devrait être un champ de mot de passe que nous devons entrer un mot de passe. Le form_widget est assez intelligent (ou plus précisément, $ form = $ this-> createForm (. ) est assez intelligent) pour créer des éléments de formulaire basés sur leur définition respective dans le Déclaration RegistrationType .

Création de l'utilisateur

Lorsque l'utilisateur clique sur le bouton "Semalt", les informations seront traitées plus loin et si tout va bien, un utilisateur sera créé.

  public function createAction (Demande $ req){$ em = $ this-> getDoctrine    -> getManager   ;$ form = $ this-> createForm (new RegistrationType   , new User   );$ form-> handleRequest ($ req);$ user = new Utilisateur   ;$ user = $ form-> getData   ;$ user-> setCreated (nouveau \ DateTime   );$ user-> setRoles ('ROLE_USER');$ user-> setGravatar ('http: // www. gravatar. com / avatar /'. md5 (trim ($ req-> get ('email'))));$ user-> setActive (true);$ pwd = $ utilisateur-> getPassword   ;$ encoder = $ this-> container-> get ('security. 

  1. $ this-> createForm sera à nouveau appelé pour générer un formulaire basé sur RegistrationType .
  2. L'objet de formulaire traitera l'entrée de l'utilisateur.
  3. Nous créons un objet User vide et en utilisant $ form-> getData , nous affectons magiquement l'entrée de formulaire aux propriétés de l'objet.
  4. Nous commençons à assigner les propriétés non renseignées par l'utilisateur: date de création, rôle, gravatar, etc.
  5. L'utilisateur peut seulement entrer son mot de passe en texte clair et l'application prend la responsabilité de le hacher. C'est exactement ce que font ces deux lignes de code.
  $ encoder = $ this-> container-> get ('security. Password_encoder');$ pwd = $ encoder-> encoderPassword ($ user, $ pwd);    

Notez que dans ces deux lignes, nous ne disons même pas au code quelle méthode de codage nous utilisons réellement. Symfony recherche simplement l'encodeur à partir de la configuration de l'application et hache le texte brut.

REMARQUE: Votre installation PHP obsolète pourrait ne pas inclure bcrypt . Si tel est le cas, veuillez utiliser composer pour installer la bibliothèque ircmaxell / password-compat .

REMARQUE: Le traitement des entrées de formulaire Symfony 2 et la manipulation des bases de données sont sûrs en ce sens qu'il gère tous les échappements nécessaires pour empêcher les entrées malveillantes et les injections SQL. Ainsi, nous pouvons affecter les entrées aux champs respectifs.

Connexion et publication

Lorsque nous faisons notre gestion des utilisateurs comme stipulé ci-dessus, le processus de connexion est simple. Nous avons déjà défini deux routes liées à la connexion:

 chemin: / loginpar défaut: {_controller: AppBundle: Security: login}login_check:chemin: / login_check    

Ensuite, nous allons créer un modèle pour afficher un formulaire de connexion de base:

  {% if error%}
{{erreur. message}}

{% fin si %}

Semalt ne sont que deux choses à noter:

  1. L'action de ce formulaire de connexion doit pointer vers {{path ('login_check'}} , ou / login_check Nous n'avons pas besoin d'implémenter ce contrôleur. le système le fera pour nous et le défaut est assez bon.
  2. Dans notre exemple, nous utilisons le nom d'utilisateur + mot de passe comme informations d'identification. Ainsi, les deux entrées dans le formulaire DOIVENT être nommées " _username " et " _password ". Ceci est requis par le système de sécurité de Symfony.

Nous pouvons également remarquer que comme nous n'utilisons pas un "type de formulaire" pour lier les informations de connexion à l'objet utilisateur sous-jacent (comme nous le faisons pour l'enregistrement), nous laissons à l'interface de sécurité widgets tous par nous-mêmes.

Semalt-le. L'utilisateur peut maintenant entrer le nom d'utilisateur et le mot de passe et se connecter.

after_login:chemin: / login_after

Dans notre application, nous avons vraiment besoin de faire quelque chose après qu'un utilisateur se connecte. Nous devons mettre à jour la dernière date et heure de connexion de l'utilisateur (champ enregistré ). Pour que cette tâche soit simple, nous devons un peu modifier notre application.

Tout d'abord, nous enregistrons un service (pour "après un événement de connexion réussi") dans le service . yml :

  services:Sécurité. authentification. success_handler:classe: AppBundle \ Handler \ AuthenticationSuccessHandlerarguments: [@security. http_utils, @service_container, {}]Mots clés:- {nom: 'monolog. enregistreur ', canal:' sécurité '}    

Ensuite, nous créons un src / AppBundle / Handler / AuthenticationHandler. Fichier php :

  class AuthenticationSuccessHandler étend DefaultAuthenticationSuccessHandler{conteneur $ protégé;fonction publique __construct (HttpUtils $ httpUtils, \ Symfony \ Component \ DependencyInjection \ ContainerInterface $ cont, array $ options){parent :: __ construct ($ httpUtils, $ options);$ this-> container = $ cont;}fonction publique onAuthenticationSuccess (\ Symfony \ Component \ HttpFoundation \ Requête $ request, \ Symfony \ Component \ Sécurité \ Core \ Authentification \ Token \ TokenInterface $ jeton){$ user = $ jeton-> getUser   ;$ user-> setLogged (nouveau \ DateTime   );$ em = $ this-> container-> get ('doctrine.orm. entity_manager');$ em-> persist ($ utilisateur);$ em-> flush   ;return $ this-> httpUtils-> createRedirectResponse ($ request, $ this-> determTargetUrl ($ request));}}    

Pour faire un bon "post-login" gestionnaire dans notre cas, il y a trois choses de la plus haute importance.

  1. Nous devons avoir accès à l'objet utilisateur pour pouvoir mettre à jour la dernière heure de connexion de l'utilisateur.
  2. Nous devons avoir accès au gestionnaire d'entités afin que l'heure de connexion puisse être conservée dans la table.
  3. Nous devons avoir accès à la requête HTTP afin qu'après la dernière mise à jour, l'application puisse toujours nous rediriger vers l'URI "cible".

Tout ceci est accompli via les arguments passés au constructeur du gestionnaire onAuthenticationSuccess :

  arguments: [@security. http_utils, @service_container, {}]    
  1. L'objet utilisateur lui-même est accessible dans la méthode onAuthenticationSuccess via $ token-> getUser .
  2. Le gestionnaire d'entités de la base de données est accessible par le conteneur de service transmis ( @service_container ) et récupéré sous la forme $ em = $ this-> container-> get ('doctrine.man or. Entity_manager' ) .
  3. La redirection est faite par $ this-> httpUtils-> createRedirectResponse , qui se référera au paramètre de @security. http_utils .

Veuillez noter que la méthode resolveTargetUrl est appelée pour créer une URI de redirection basée sur la requête $ . Normalement, nous pouvons visiter divers URI: la page d'index, ou un lien spécifique vers un article. Nous pouvons jeter un oeil à l'implémentation de cette méthode dans la source de Symfony 2 ( racine_projet / fournisseur / symfony / symfony / src / Symfony / Component / Sécurité / Http / Authentication / AuthenticationSuccessHandler. '. $ this-> providerKey. '. target_path ')) {$ request-> getSession -> remove ('_ security.'. $ this-> providerKey. '. target_path');return $ targetUrl;}if ($ this-> options ['use_referer'] && ($ targetUrl = $ demande-> en-têtes-> get ('Referer')) && $ targetUrl! == $ this-> httpUtils-> generateUri ($ request, $ this-> options ['login_path'])) {return $ targetUrl;}return $ this-> options ['default_target_path'];}}

Il explique la logique sur la façon dont finalement un URI cible (normalement l'URI qui déclenche la connexion) est déterminé.

Conclusion

Nous venons de couvrir avec succès deux aspects importants du développement d'applications avec Symfony2:

  1. Enregistrement (et invitation)
  2. Connexion (et connexion à un compte)

Une tendance récente dans les sites Web utilise les informations d'identification des réseaux sociaux (G +, Facebook, etc.) pour faciliter le processus d'enregistrement / connexion. Cependant, une simple inscription / connexion interne est toujours d'une importance critique pour certaines applications. De plus, la compréhension de l'ensemble du processus d'enregistrement / connexion nous aide à comprendre le système de sécurité de Symfony2.

Si vous souhaitez voir plus de contenu sur des points connexes, comme la validation par exemple, ou juste avoir des commentaires ou des commentaires sur ce tutoriel, s'il vous plaît laissez-nous savoir!

March 7, 2018