Comment créer une garde d'authentification personnalisée dans Laravel

Dans cet article, nous allons couvrir le système d'authentification dans le framework Laravel. L'objectif principal de cet article est de créer une protection d'authentification personnalisée en étendant le système d'authentification principal..

Laravel fournit un système d'authentification très solide dans le noyau qui facilite grandement la mise en œuvre de l'authentification de base. En fait, il vous suffit d'exécuter deux commandes artisanales pour configurer l'échafaudage d'un système d'authentification..

De plus, le système lui-même est conçu de manière à pouvoir être étendu et connecté à vos adaptateurs d’authentification personnalisés. C'est ce que nous allons discuter en détail tout au long de cet article. Avant de nous lancer dans l'implémentation de la protection d'authentification personnalisée, nous allons commencer par une discussion des éléments de base des protecteurs et des systèmes d'authentification Laravel..

Les éléments fondamentaux: gardes et fournisseurs

Le système d’authentification Laravel est composé de deux éléments: ses gardes centrales et ses fournisseurs.

Gardes

Vous pourriez penser à un garde comme un moyen de fournir la logique utilisée pour identifier les utilisateurs authentifiés. Dans le noyau, Laravel fournit différents gardes comme session et jeton. Le gardien de session maintient l'état de l'utilisateur dans chaque demande par le biais de cookies. D'autre part, le gardien de jeton authentifie l'utilisateur en vérifiant un jeton valide dans chaque demande..

Ainsi, comme vous pouvez le constater, la protection définit la logique de l’authentification et il n’est pas nécessaire qu’elle traite toujours de cette information en récupérant des informations d’identification valides à partir du serveur principal. Vous pouvez implémenter une protection qui vérifie simplement la présence d’un élément spécifique dans les en-têtes de demande et authentifie les utilisateurs en fonction de cet élément..

Plus loin dans cet article, nous allons implémenter une protection qui vérifie certains paramètres JSON dans les en-têtes de requête et récupère l'utilisateur valide à partir du back-end de MongoDB..

Fournisseurs

Si la protection définit la logique d'authentification, le fournisseur d'authentification est chargé de récupérer l'utilisateur à partir du stockage principal. Si le service de garde exige que l'utilisateur soit validé par rapport au stockage principal, la mise en œuvre de la récupération de l'utilisateur passe par le fournisseur d'authentification..

Laravel est livré avec deux fournisseurs d'authentification par défaut, Database et Eloquent. Le fournisseur d'authentification de base de données traite de la récupération directe des informations d'identification de l'utilisateur à partir du stockage principal, tandis qu'Eloquent fournit une couche d'abstraction qui effectue les tâches nécessaires..

Dans notre exemple, nous allons implémenter un fournisseur d'authentification MongoDB qui récupère les informations d'identification de l'utilisateur à partir du backend MongoDB..

C'était donc une introduction de base aux gardes et aux fournisseurs dans le système d'authentification Laravel. À partir de la section suivante, nous nous concentrerons sur le développement de la protection d’authentification personnalisée et du fournisseur.!

Un coup d'œil sur la configuration du fichier

Regardons rapidement la liste des fichiers que nous allons implémenter tout au long de cet article..

  • config / auth.php: C'est le fichier de configuration de l'authentification dans lequel nous allons ajouter une entrée de notre garde personnalisée.
  • config / mongo.php: C'est le fichier qui contient la configuration MongoDB.
  • app / Services / Contrats / NosqlServiceInterface.php: C'est une interface que notre classe de base de données Mongo personnalisée implémente.
  • app / Database / MongoDatabase.php: C'est une classe de base de données principale qui interagit avec MongoDB.
  • app / Models / Auth / User.php: C'est la classe de modèle utilisateur qui implémente le contrat Authenticable.
  • app / Extensions / MongoUserProvider.php: C'est une implémentation du fournisseur d'authentification.
  • app / Services / Auth / JsonGuard.php: C'est une implémentation du pilote d'authentification.
  • app / Providers / AuthServiceProvider.php: Ceci est un fichier existant que nous allons utiliser pour ajouter nos liaisons de conteneur de service.
  • app / Http / Controllers / MongoController.php: C'est un fichier de contrôleur de démonstration que nous allons implémenter pour tester notre garde personnalisée.

Ne vous inquiétez pas si la liste des fichiers n'a pas encore beaucoup de sens car nous discuterons de tout en détail au fur et à mesure que nous le parcourrons..

Plongez dans l'implémentation

Dans cette section, nous allons passer en revue la mise en œuvre des fichiers requis..

La première chose à faire est d'informer Laravel de notre garde sur mesure. Allez-y et entrez les détails de la garde personnalisée dans le champ config / auth.php fichier comme indiqué.

… 'Gardes' => ['web' => ['driver' => 'session', 'provider' => 'utilisateurs',], 'api' => ['driver' => 'jeton', 'provider '=>' utilisateurs ',],' custom '=> [' driver '=>' json ',' provider '=>' mongo ',],],… 

Comme vous pouvez le constater, nous avons ajouté notre garde personnalisée sous le Douane clé.

Ensuite, nous devons ajouter une entrée de fournisseur associé dans le fournisseurs section.

… 'Providers' => ['users' => ['driver' => 'eloquent', 'model' => App \ User :: class,], 'mongo' => ['driver' => 'mongo' ], // 'utilisateurs' => [// 'pilote' => 'base de données', // 'table' => 'utilisateurs', //],],… 

Nous avons ajouté notre entrée de fournisseur sous le mongo clé.

Enfin, changeons la protection d’authentification par défaut de Web à personnalisée.

… 'Defaults' => ['guard' => 'custom', 'passwords' => 'users',],… 

Bien sûr, cela ne fonctionnera pas encore car nous n’avons pas encore implémenté les fichiers nécessaires. Et c'est ce que nous allons discuter dans les deux prochaines sections.

Configurer le pilote MongoDB

Dans cette section, nous allons implémenter les fichiers nécessaires qui parlent à l'instance sous-jacente MongoDB..

Commençons par créer un fichier de configuration config / mongo.php qui contient les paramètres de connexion par défaut MongoDB.

 ['hôte' => 'HOST_IP', 'port' => 'HOST_PORT', 'base de données' => 'DB_NAME']];

Bien sûr, vous devez modifier les valeurs d’espace réservé conformément à vos paramètres..

Au lieu de créer directement une classe qui interagit avec MongoDB, nous allons créer une interface en premier lieu.

L'avantage de créer une interface est qu'elle fournit un contrat qu'un développeur doit respecter lors de sa mise en œuvre. De plus, notre implémentation de MongoDB pourrait être facilement remplacée par une autre implémentation NoSQL si nécessaire..

Allez-y et créez un fichier d'interface app / Services / Contrats / NosqlServiceInterface.php avec le contenu suivant.

C'est une interface assez simple qui déclare les méthodes de base CRUD qu'une classe doit définir pour implémenter cette interface..

Maintenant, définissons une classe réelle à app / Database / MongoDatabase.php.

connection = new MongoClient ("mongodb: // $ host: $ port"); $ this-> database = $ this-> connection -> $ database;  / ** * @see \ App \ Services \ Contracts \ NosqlServiceInterface :: find () * / fonction publique find ($ collection, Array $ criteres) return $ this-> base de données -> $ collection -> findOne ( $ critères);  fonction publique create ($ collection, Array $ document)  mise à jour de la fonction publique ($ collection, $ id, Array $ document)  fonction publique delete ($ collection, $ id) 

Bien entendu, je suppose que vous avez installé MongoDB et l’extension PHP correspondante..

le __construction méthode instancie la MongoClient classe avec les paramètres nécessaires. L’autre méthode importante qui nous intéresse est la trouver method, qui récupère l'enregistrement en fonction des critères fournis en tant qu'arguments de la méthode.

C’était donc l’implémentation du pilote MongoDB, et j’ai essayé de le garder le plus simple possible.

Configurer le modèle utilisateur

En adhérant aux normes du système d’authentification, nous devons implémenter le modèle utilisateur qui doit implémenter le Illuminer \ Contrats \ Auth \ Authentifiable Contrat.

Allez-y et créez un fichier app / Models / Auth / User.php avec le contenu suivant.

conn = $ conn;  / ** * Recherche d'utilisateur par informations d'identification * * @param array $ informations d'identification * @return Illuminate \ Contracts \ Auth \ Authenticatable * / fonction publique fetchUserByCredentials (Tableau $ informations d'identification) $ arr_user = $ this-> conn-> find- () utilisateurs ', [' username '=> $ credentials [' username ']]); if (! is_null ($ arr_user)) $ this-> nom d'utilisateur = $ arr_user ['nom d'utilisateur']; $ this-> password = $ arr_user ['password'];  return $ this;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthIdentifierName () * / public function getAuthIdentifierName () return "nomutilisateur";  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthIdentifier () * / fonction publique getAuthIdentifier () return $ this -> $ this-> getAuthIdentifierName ();  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthPassword () * / fonction publique getAuthPassword () return $ this-> mot de passe;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getRememberToken () * / fonction publique getRememberToken () if (! vide ($ this-> getRememberTokenName ())) return $ this -> $ this-> getRememberTokenName ();  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: setRememberToken () * / fonction publique setRememberToken ($ value) if (! vide ($ this-> getRememberTokenName ())) $ this -> $ this-> getRememberTokenName () = $ value;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getRememberTokenName () * / fonction publique getRememberTokenName () return $ this-> RememberTokenName; 

Vous devriez déjà avoir remarqué que App \ Models \ Auth \ User met en œuvre le Illuminer \ Contrats \ Auth \ Authentifiable Contrat.

La plupart des méthodes mises en œuvre dans notre classe s'expliquent d'elles-mêmes. Cela dit, nous avons défini le fetchUserByCredentials méthode, qui récupère l'utilisateur à partir du back-end disponible. Dans notre cas, ça va être un MongoDatabase classe qui sera appelée à récupérer les informations nécessaires.

Voilà donc la mise en œuvre du modèle utilisateur.

Configurer le fournisseur d'authentification

Comme nous l'avons vu précédemment, le système d'authentification Laravel est composé de deux éléments: des gardes et des fournisseurs..

Dans cette section, nous allons créer un fournisseur d’authentification qui traite de la récupération des utilisateurs à partir du serveur principal..

Allez-y et créez un fichier app / Extensions / MongoUserProvider.php comme indiqué ci-dessous.

model = $ userModel;  / ** * Récupère un utilisateur à l'aide des informations d'identification fournies. * * @param array $ credentials * @return \ Illuminate \ Contrats \ Auth \ Authenticatable | null * / fonction publique retrieveByCredentials (array $ credentials) if (vide ($ credentials))) return;  $ user = $ this-> model-> fetchUserByCredentials (['username' => $ credentials ['username']]); return $ user;  / ** * Valider un utilisateur en fonction des informations d'identification fournies. * * @param \ Illuminate \ Contracts \ Auth \ Authenticatable $ user * @param array $ credentials Demander les informations d'identification * @return bool * / public function validateCredentials (Authenticatable $ user, Array $ credentials) return ($ credentials ['username']] == $ user-> getAuthIdentifier () && md5 ($ credentials ['password']) == $ user-> getAuthPassword ());  fonction publique retrieveById ($ identifier) ​​ fonction publique retrieveByToken ($ identifiant, $ jeton)  fonction publique updateRememberToken (Authenticatable $ utilisateur, $ jeton) 

Là encore, vous devez vous assurer que le fournisseur personnalisé doit implémenter le Illuminate \ Contracts \ Auth \ UserProvider Contrat.

Pour aller de l'avant, il définit deux méthodes importantes: retrieveByCredentials et validateCredentials..

le récupérer par les informations d'identification La méthode est utilisée pour récupérer les informations d'identification de l'utilisateur à l'aide de la classe de modèle User décrite dans la section précédente. D'autre part, le validateCredentials La méthode est utilisée pour valider un utilisateur par rapport au jeu donné d'informations d'identification..

Et ce fut la mise en œuvre de notre fournisseur d'authentification personnalisé. Dans la section suivante, nous allons créer une garde qui interagit avec le MongoUserProvider fournisseur d'authentification.

Configurer la garde d'authentification

Comme nous en avons discuté précédemment, le système de protection du système d’authentification de Laravel définit le mode d’authentification de l’utilisateur. Dans notre cas, nous vérifierons la présence du Jsondata paramètre de demande qui doit contenir la chaîne codée JSON des informations d'identification.

Dans cette section, nous allons créer une protection qui interagit avec le fournisseur d'authentification qui vient d'être créé dans la dernière section..

Allez-y et créez un fichier app / Services / Auth / JsonGuard.php avec le contenu suivant.

request = $ request; $ this-> provider = $ provider; $ this-> user = NULL;  / ** * Détermine si l'utilisateur actuel est authentifié. * * @return bool * / vérification de la fonction publique () return! is_null ($ this-> user ());  / ** * Détermine si l'utilisateur actuel est un invité. * * @return bool * / fonction publique invité () return! $ this-> check ();  / ** * Récupère l'utilisateur actuellement authentifié. * * @return \ Illuminate \ Contracts \ Auth \ Authenticatable | null * / fonction publique user () if (! is_null ($ this-> utilisateur)) return $ this-> utilisateur;  / ** * Récupère les paramètres JSON de la requête en cours * * @ chaîne de retour * / fonction publique getJsonParams () $ jsondata = $ this-> request-> query ('jsondata'); return (! empty ($ jsondata)? json_decode ($ jsondata, TRUE): NULL);  / ** * Obtenir l'ID de l'utilisateur actuellement authentifié. * * @retour string | null * / fonction publique id () if ($ utilisateur = $ ceci-> utilisateur ()) retour $ ceci-> utilisateur () -> getAuthIdentifier ();  / ** * Valider les informations d'identification d'un utilisateur. * * @return bool * / fonction publique validate (Array $ credentials = []) if (vide ($ credentials ['nomutilisateur'])) || empty ($ credentials ['mot de passe'])) if (! $ credentials = $ this-> getJsonParams ()) return false;  $ user = $ this-> provider-> retrieveByCredentials ($ credentials); if (! is_null ($ user) && $ this-> fournisseur-> validateCredentials ($ user, $ credentials)) $ this-> setUser ($ user); retourne vrai;  else return false;  / ** * Définir l'utilisateur actuel. * * @param Array $ user User info * @return void * / public function setUser (Authenticatable $ user) $ this-> user = $ user; return $ this; 

Tout d’abord, notre classe doit mettre en œuvre la Illuminer \ Contrats \ Auth \ Garde interface. Il faut donc définir toutes les méthodes déclarées dans cette interface..

La chose importante à noter ici est que le __construction fonction nécessite une mise en œuvre de Illuminate \ Contracts \ Auth \ UserProvider. Dans notre cas, nous allons passer une instance de App \ Extensions \ MongoUserProvider, comme nous le verrons dans la dernière section.

Ensuite, il y a une fonction getJsonParams qui récupère les informations d'identification de l'utilisateur à partir du paramètre de requête nommé Jsondata. Comme nous nous attendons à recevoir une chaîne codée JSON des informations d’identité de l’utilisateur, nous avons utilisé le json_decode fonction pour décoder les données JSON.

Dans la fonction validate, la première chose que nous vérifions est l’existence du $ informations d'identification argument. Si ce n'est pas présent, nous appellerons le getJsonParams méthode pour récupérer les informations d'identification de l'utilisateur à partir des paramètres de la demande.

Ensuite, nous appelons le récupérer par les informations d'identification méthode du MongoUserProvider fournisseur qui récupère l’utilisateur de la base de données MongoDB. Enfin, c'est le validateCredentials méthode du MongoUserProvider fournisseur qui vérifie la validité de l'utilisateur.

C'était donc la mise en œuvre de notre garde de douane. La section suivante explique comment assembler ces éléments pour former un système d’authentification réussi..

Mettre tous ensemble

Jusqu'à présent, nous avons développé tous les éléments de la protection d'authentification personnalisée qui devrait nous fournir un nouveau système d'authentification. Cependant, cela ne fonctionnera pas immédiatement car nous devons d'abord l'enregistrer à l'aide des liaisons du conteneur de services Laravel..

Comme vous le savez sûrement déjà, le fournisseur de services Laravel est le bon endroit pour mettre en œuvre les liaisons nécessaires..

Allez-y et ouvrez le fichier app / Providers / AuthServiceProvider.php cela nous permet d'ajouter des liaisons de conteneur de service d'authentification. S'il ne contient aucune modification personnalisée, vous pouvez simplement le remplacer par le contenu suivant..

 'App \ Policies \ ModelPolicy',]; / ** * Enregistrez tous les services d'authentification / autorisation. * * @return void * / public function boot () $ this-> registerPolicies (); $ this-> app-> bind ('App \ Base de données \ MongoDatabase', fonction ($ app) retourne la nouvelle MongoDatabase (config ('mongo.defaults.host'), config ('mongo.defaults.port'), config ('mongo.defaults.database'));); $ this-> app-> bind ('App \ Models \ Auth \ Utilisateur', fonction ($ app) retourne le nouvel utilisateur ($ app-> make ('App \ Base de données \ MongoDatabase'));); // ajout du fournisseur de gardes personnalisé Auth :: provider ('mongo', function ($ app, array $ config) retourne un nouveau MongoUserProvider ($ app-> make ('App \ Models \ Auth \ User'));); // ajoute un garde personnalisé Auth :: extend ('json', fonction ($ app, $ nom, tableau $ config) retourne un nouveau JsonGuard (Auth :: createUserProvider ($ config ['fournisseur']), $ app-> make ('demande')); );  public function register () $ this-> app-> bind ('App \ Services \ Contrats \ NosqlServiceInterface', 'App \ Base de données \ MongoDatabase'); 

Passons à travers le démarrage méthode qui contient la plupart des liaisons de fournisseur.

Pour commencer, nous allons créer des liaisons pour le App \ Database \ MongoDatabase et App \ Models \ Auth \ User éléments.

$ this-> app-> bind ('App \ Base de données \ MongoDatabase', fonction ($ app) retourne la nouvelle MongoDatabase (config ('mongo.defaults.host'), config ('mongo.defaults.port'), config ('mongo.defaults.database'));); $ this-> app-> bind ('App \ Models \ Auth \ Utilisateur', fonction ($ app) retourne le nouvel utilisateur ($ app-> make ('App \ Base de données \ MongoDatabase')););

Cela fait un moment que nous parlons de fournisseur et de gardien, et il est temps de brancher notre garde personnalisée au système d'authentification Laravel..

Nous avons utilisé la méthode du fournisseur du Auth Façade pour ajouter notre fournisseur d'authentification personnalisé sous la clé mongo. Rappelez-vous que la clé reflète les paramètres ajoutés précédemment dans la liste. auth.php fichier.

Auth :: provider ('mongo', function ($ app, array $ config) renvoie le nouveau MongoUserProvider ($ app-> make ('App \ Models \ Auth \ User')););

De la même manière, nous allons injecter notre implémentation de garde personnalisée en utilisant la méthode extend du Auth façade.

Auth :: extend ('json', fonction ($ app, $ name, tableau $ config) retourne un nouveau JsonGuard (Auth :: createUserProvider ($ config ['fournisseur']), $ app-> make ('request') ););

Ensuite, il y a un registre méthode que nous avons utilisée pour lier le App \ Services \ Contracts \ NosqlServiceInterface interface au App \ Database \ MongoDatabase la mise en oeuvre.

$ this-> app-> bind ('App \ Services \ Contracts \ NosqlServiceInterface', 'App \ Base de données \ MongoDatabase');

Donc, chaque fois qu'il y a un besoin de résoudre le App \ Services \ Contracts \ NosqlServiceInterface dépendance, Laravel répond par la mise en œuvre de la App \ Database \ MongoDatabase adaptateur.

L'avantage d'utiliser cette approche est que l'on peut facilement échanger l'implémentation donnée avec une implémentation personnalisée. Par exemple, supposons que quelqu'un veuille remplacer le App \ Database \ MongoDatabase implémentation avec l’adaptateur CouchDB à l’avenir. Dans ce cas, il suffit d’ajouter la liaison correspondante dans la méthode register.

C'était donc le fournisseur de services à votre disposition. À l'heure actuelle, nous disposons de tout ce qui est nécessaire pour tester notre implémentation de protection personnalisée. La section suivante, qui porte sur la conclusion, traite de ce sujet..

Est-ce que ça marche?

Vous avez travaillé d'arrache-pied pour configurer votre premier dispositif de protection par authentification personnalisée. Il est temps de tirer parti des avantages qui s'offrent à vous et de l'essayer..

Implémentons rapidement un fichier de contrôleur assez basique app / Http / Controllers / MongoController.php comme indiqué ci-dessous.

validate ()) // récupère l'utilisateur authentifié actuel $ user = $ auth_guard-> user (); echo 'Success!'  else echo 'Non autorisé à accéder à cette page!'; 

Examinez de près la dépendance de la méthode de connexion, qui nécessite la mise en œuvre de la Illuminer \ Contrats \ Auth \ Garde garde. Depuis que nous avons mis la Douane garde en tant que garde par défaut dans le auth.php fichier, c'est le App \ Services \ Auth \ JsonGuard ça va être injecté réellement!

Ensuite, nous avons appelé le valider méthode du App \ Services \ Auth \ JsonGuard class, qui à son tour initie une série d'appels de méthodes:

  • Il appelle le récupérer par les informations d'identification méthode du App \ Extensions \ MongoUserProvider classe.
  • le récupérer par les informations d'identification la méthode appelle le fetchUserByCredentials méthode de l'utilisateur App \ Models \ Auth \ User classe.
  • le fetchUserByCredentials la méthode appelle le trouver méthode du App \ Database \ MongoDatabase récupérer les informations d'identification de l'utilisateur.
  • Finalement, le trouver méthode du App \ Database \ MongoDatabase renvoie la réponse!

Si tout fonctionne comme prévu, nous devrions obtenir un utilisateur authentifié en appelant le utilisateur méthode de notre garde.

Pour accéder au contrôleur, vous devez ajouter un itinéraire associé dans le routes / web.php fichier.

Route :: get ('/ custom / mongo / login', 'MongoController @ login');

Essayez d’accéder à l’URL http: // votre-site-laravel / custom / mongo / login sans passer aucun paramètre et vous devriez voir un message "non autorisé".

D'autre part, essayez quelque chose comme http: // votre-site-laravel / custom / mongo / login? Jsondata = "nom d'utilisateur": "admin", "mot de passe": "admin" et qui devrait renvoyer un message de réussite. si l'utilisateur est présent dans votre base de données.

Veuillez noter qu'il ne s'agit que d'exemples illustrant le fonctionnement de la protection personnalisée. Vous devez implémenter une solution infaillible pour une fonctionnalité telle que la connexion. En fait, je viens de donner un aperçu du flux d'authentification; vous êtes responsable de la création d'une solution robuste et sécurisée pour votre application.

Cela met fin à notre voyage d’aujourd’hui et j'espère pouvoir revenir avec des informations plus utiles. Si vous voulez que j'écrive sur un sujet spécifique, n'oubliez pas de me laisser un message!

Conclusion

Le framework Laravel fournit un système d’authentification solide dans le noyau qui peut être étendu si vous souhaitez implémenter un système personnalisé. C'était le sujet de l'article d'aujourd'hui pour implémenter une protection personnalisée et la brancher sur le flux de travail de l'authentification Laravel..

Au cours de cette opération, nous avons mis au point un système qui authentifie l'utilisateur sur la base de la charge utile JSON de la demande et le met en correspondance avec la base de données MongoDB. Et pour y parvenir, nous avons créé une protection personnalisée et une implémentation personnalisée du fournisseur..

J'espère que l'exercice vous a fourni un aperçu du processus d'authentification de Laravel et que vous devriez maintenant vous sentir plus confiant quant à son fonctionnement interne..

Pour ceux d'entre vous qui débutent avec Laravel ou qui souhaitent développer leurs connaissances, leur site ou leur application avec des extensions, nous pouvons étudier de nombreuses choses sur le marché Envato..

J'aimerais entendre vos commentaires et suggestions, alors criez fort en utilisant le flux ci-dessous!