Hoe maak je een aangepaste authenticatie bewaker in Laravel

In dit artikel gaan we het authenticatiesysteem in het Laravel-framework behandelen. Het belangrijkste doel van dit artikel is om een ​​aangepaste authenticatiebescherming te maken door het kernauthenticatiesysteem uit te breiden.

Laravel biedt in de kern een zeer solide authenticatiesysteem dat de implementatie van basisverificatie een eitje maakt. In feite hoeft u slechts een paar ambachtelijke opdrachten uit te voeren om de steiger van een authenticatiesysteem in te stellen.

Bovendien is het systeem zelf zo ontworpen dat u het kunt uitbreiden en ook uw aangepaste authenticatie-adapters kunt aansluiten. Dat is wat we in dit artikel in detail bespreken. Voordat we verder gaan met de implementatie van de aangepaste authenticatiebewaker, beginnen we met een bespreking van de basiselementen in de Laravel-authenticatiesysteem-bewakers en providers.

De kernelementen: bewakers en providers

Het Laravel-authenticatiesysteem bestaat uit twee elementen bij de kernwachters en providers.

Guards

Je zou een bewaker kunnen zien als een manier om de logica te leveren die wordt gebruikt om de geverifieerde gebruikers te identificeren. In de kern biedt Laravel verschillende bewakers, zoals sessie en token. De sessiebewaker handhaaft de status van de gebruiker in elk verzoek door cookies, en aan de andere kant authenticeert de tokenbewaker de gebruiker door een geldig token in elk verzoek te controleren.

Dus, zoals je kunt zien, definieert de bewaker de logica van authenticatie, en het is niet nodig dat het daar altijd mee omgaat door geldige inloggegevens op te halen van de achterkant. U kunt een bewaker implementeren die eenvoudig de aanwezigheid van een specifiek ding in de headers van aanvragen controleert en gebruikers op basis daarvan verifieert.

Verderop in dit artikel zullen we een bewaker implementeren die bepaalde JSON-parameters in request-headers controleert en de geldige gebruiker terughaalt van de MongoDB-back-end.

providers

Als de bewaker de logica van de verificatie definieert, is de verificatieprovider verantwoordelijk voor het ophalen van de gebruiker uit de back-endopslag. Als de bewaker vereist dat de gebruiker moet worden gevalideerd tegen de back-endopslag, gaat de implementatie van het ophalen van de gebruiker naar de authenticatieprovider.

Laravel wordt geleverd met twee standaard authenticatieproviders: Database en Eloquent. De database-authenticatieprovider houdt zich bezig met het eenvoudig ophalen van de gebruikersreferenties uit de back-endopslag, terwijl Eloquent een abstractielaag biedt die de nodige.

In ons voorbeeld zullen we een MongoDB-authenticatieprovider implementeren die de gebruikersreferenties ophaalt van de MongoDB-back-end.

Dus dat was een basisintroductie voor bewakers en providers in het Laravel-authenticatiesysteem. Vanaf het volgende gedeelte zullen we ons concentreren op de ontwikkeling van de aangepaste authenticatiebewaker en -provider!

Een snelle blik op de bestandsinstellingen

Laten we even kijken naar de lijst met bestanden die we in de loop van dit artikel zullen implementeren.

  • config / auth.php: Het is het authenticatieconfiguratiebestand waarin we een vermelding van onze aangepaste bewaker toevoegen.
  • config / mongo.php: Het is het bestand dat de MongoDB-configuratie bevat.
  • app / Diensten / Contracten / NosqlServiceInterface.php: Het is een interface die door onze aangepaste Mongo-databaseklasse wordt geïmplementeerd.
  • app / Database / MongoDatabase.php: Het is een hoofddatabase-klasse die samenwerkt met MongoDB.
  • app / Modellen / Auth / User.php: Het is de klasse User-model die het Authenticable-contract implementeert.
  • app / Extensions / MongoUserProvider.php: Het is een implementatie van de authenticatieprovider.
  • app / Diensten / Auth / JsonGuard.php: Het is een implementatie van de driver voor authenticatiebescherming.
  • app / Providers / AuthServiceProvider.php: Dit is een bestaand bestand dat we zullen gebruiken om onze service containerverbindingen toe te voegen.
  • app / Http / Controllers / MongoController.php: Het is een demo-controllerbestand dat we zullen implementeren om onze aangepaste bewaker te testen.

Maak je geen zorgen als de lijst met bestanden nog niet veel zin heeft, want we zullen alles in detail bespreken terwijl we het doornemen.

Duik diep in de implementatie

In deze sectie zullen we de implementatie van de vereiste bestanden doornemen.

Het eerste dat we moeten doen is Laravel informeren over onze aangepaste bewaker. Ga je gang en voer de aangepaste bewakingsdetails in de config / auth.php bestand zoals getoond.

... 'guards' => ['web' => ['driver' => 'sessie', 'provider' => 'gebruikers',], 'api' => ['driver' => 'token', 'provider '=>' gebruikers ',],' aangepast '=> [' stuurprogramma '=>' json ',' provider '=>' mongo ',],], ... 

Zoals u kunt zien, hebben we onze aangepaste bewaking toegevoegd onder de gewoonte sleutel.

Vervolgens moeten we een bijbehorend provider-item toevoegen in de providers sectie.

... 'providers' => ['users' => ['driver' => 'eloquent', 'model' => App \ Gebruiker :: class,], 'mongo' => ['driver' => 'mongo' ], // 'gebruikers' => [// 'stuurprogramma' => 'database', // 'tabel' => 'gebruikers', //],], ... 

We hebben onze provider-vermelding toegevoegd onder de mongo sleutel.

Laten we ten slotte de standaardverificatiebewaking wijzigen van internet naar aangepast.

... 'defaults' => ['bewaking' => 'aangepast', 'wachtwoorden' => 'gebruikers',], ... 

Natuurlijk werkt het nog niet, omdat we de benodigde bestanden nog niet hebben geïmplementeerd. En dat is wat we in de volgende paragrafen zullen bespreken.

Stel het MongoDB stuurprogramma in

In deze sectie zullen we de nodige bestanden implementeren die praten met de onderliggende MongoDB-instantie.

Laten we eerst een configuratiebestand maken config / mongo.php die de standaard MongoDB-verbindingsinstellingen bevat.

 ['host' => 'HOST_IP', 'poort' => 'HOST_PORT', 'database' => 'DB_NAME']];

Natuurlijk moet u de waarden voor de tijdelijke aanduiding wijzigen volgens uw instellingen.

In plaats van rechtstreeks een klasse te maken die samenwerkt met MongoDB, zullen we in de eerste plaats een interface maken.

Het voordeel van het maken van een interface is dat deze een contract biedt waaraan een ontwikkelaar zich moet houden tijdens de implementatie. Ook zou onze implementatie van MongoDB gemakkelijk kunnen worden geruild met een andere NoSQL-implementatie, indien nodig.

Ga je gang en maak een interfacebestand aan app / Diensten / Contracten / NosqlServiceInterface.php met de volgende inhoud.

Het is een vrij eenvoudige interface die de basis CRUD-methoden declareert die een klasse moet definiëren die deze interface implementeert.

Laten we nu een echte klasse definiëren op app / Database / MongoDatabase.php.

connection = new MongoClient ("mongodb: // $ host: $ port"); $ this-> database = $ this-> connection -> $ database;  / ** * @see \ App \ Services \ Contracts \ NosqlServiceInterface :: find () * / public function find ($ collection, Array $ criteria) return $ this-> database -> $ collection -> findOne ( $ criteria);  openbare functie maken ($ collectie, Array $ -document)  openbare functie-update ($ collectie, $ id, Array $ -document)  openbare functie verwijderen ($ collection, $ id) 

Natuurlijk neem ik aan dat je MongoDB en de bijbehorende MongoDB PHP-extensie hebt geïnstalleerd.

De __construct methode maakt het MongoClient klasse met de nodige parameters. De andere belangrijke methode waarin we geïnteresseerd zijn, is de vind methode, die de record ophaalt op basis van de criteria die als methodeargumenten zijn opgegeven.

Dus dat was de implementatie van de MongoDB-driver en ik probeerde het zo simpel mogelijk te houden.

Stel het gebruikersmodel in

Als we ons houden aan de normen van het authenticatiesysteem, moeten we het gebruikersmodel implementeren dat de Verlichten \ contracten \ Auth \ authentiseerbare contract.

Ga je gang en maak een bestand aan app / Modellen / Auth / User.php met de volgende inhoud.

conn = $ conn;  / ** * Gebruiker ophalen op basis van referenties * * @param array $ referenties * @return Illuminate \ Contracts \ Auth \ Authenticatable * / public function fetchUserByCredentials ($ credentials) $ arr_user = $ this-> conn-> find (' gebruikers ', [' gebruikersnaam '=> $ inloggegevens [' gebruikersnaam ']]); if (! is_null ($ arr_user)) $ this-> gebruikersnaam = $ arr_user ['gebruikersnaam']; $ this-> wachtwoord = $ arr_user ['wachtwoord'];  retourneer $ dit;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthIdentifierName () * / public function getAuthIdentifierName () retour "gebruikersnaam";  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthIdentifier () * / public function getAuthIdentifier () return $ this -> $ this-> getAuthIdentifierName ();  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthPassword () * / public function getAuthPassword () return $ this-> wachtwoord;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getRememberToken () * / public function getRememberToken () if (! empty ($ this-> getRememberTokenName ())) retourneer $ deze -> $ this-> getRememberTokenName ();  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: setRememberToken () * / public function setRememberToken ($ value) if (! empty ($ this-> getRememberTokenName ())) $ this -> $ this-> getRememberTokenName () = $ waarde;  / ** * @inheritDoc * @see \ Illuminate \ Contracts \ Auth \ Authenticatable :: getRememberTokenName () * / public function getRememberTokenName () return $ this-> rememberTokenName; 

Dat had je al moeten merken App \ Models \ Auth \ User implementeert de Verlichten \ contracten \ Auth \ authentiseerbare contract.

De meeste methoden die in onze klas worden toegepast, spreken voor zich. Dat gezegd hebbende, hebben we de fetchUserByCredentials methode, die de gebruiker terughaalt van de beschikbare back-end. In ons geval zal het een zijn MongoDatabase klasse die wordt opgeroepen om de benodigde informatie op te halen.

Dus dat is de implementatie van het gebruikersmodel.

Stel de authenticatieprovider in

Zoals we eerder hebben besproken, bestaat het Laravel-authenticatiesysteem uit twee elementen: bewakers en providers.

In deze sectie maken we een authenticatieprovider die zich bezig houdt met het ophalen door de gebruiker vanaf de achterkant.

Ga je gang en maak een bestand aan app / Extensions / MongoUserProvider.php zoals hieronder getoond.

model = $ userModel;  / ** * Haal een gebruiker op met de opgegeven inloggegevens. * * @param array $ referenties * @return \ Illuminate \ Contracts \ Auth \ Authenticatable | null * / public function retrieveByCredentials (array $ credentials) if (empty ($ credentials)) return;  $ user = $ this-> model-> fetchUserByCredentials (['username' => $ credentials ['username']]); return $ user;  / ** * Valideer een gebruiker tegen de opgegeven inloggegevens. * * @param \ Illuminate \ Contracts \ Auth \ Authenticatable $ user * @param array $ credentials Aanvraagreferenties * @return bool * / public function validateCredentials (Authenticatable $ user, Array $ credentials) return ($ credentials ['gebruikersnaam'] == $ user-> getAuthIdentifier () && md5 ($ credentials ['password']) == $ user-> getAuthPassword ());  openbare functie retrieveById ($ identifier) ​​ openbare functie retrieveByToken ($ identifier, $ token)  public function updateRememberToken (Authenticatable $ user, $ token) 

Nogmaals, u moet ervoor zorgen dat de aangepaste provider de Verlichten \ contracten \ Auth \ UserProvider contract.

Voor de toekomst worden twee belangrijke methoden gedefinieerd: retriveByCredentials en validationCredentials.

De retrieveByCredentials methode wordt gebruikt om de gebruikersreferenties op te halen met behulp van de gebruikersmodelklasse die in de vorige sectie is besproken. Aan de andere kant, de validateCredentials methode wordt gebruikt om een ​​gebruiker te valideren tegen de gegeven set referenties.

En dat was de implementatie van onze aangepaste authenticatieprovider. In het volgende gedeelte gaan we door en maken we een bewaker die interactie heeft met de MongoUserProvider authenticatie provider.

Stel de authenticatiebescherming in

Zoals we eerder hebben besproken, bepaalt de bewaker in het Laravel-authenticatiesysteem hoe de gebruiker wordt geverifieerd. In ons geval controleren we de aanwezigheid van de jsondata vraag parameter aan die de JSON-gecodeerde reeks van de inloggegevens moet bevatten.

In deze sectie maken we een bewaker die interactie heeft met de authenticatieprovider die zojuist in de laatste sectie is gemaakt.

Ga je gang en maak een bestand aan app / Diensten / Auth / JsonGuard.php met de volgende inhoud.

request = $ request; $ this-> provider = $ provider; $ this-> user = NULL;  / ** * Bepaal of de huidige gebruiker is geverifieerd. * * @return bool * / openbare functiecontrole () ga terug! is_null ($ this-> gebruiker ());  / ** * Bepaal of de huidige gebruiker een gast is. * * @return bool * / public function guest () keer terug! $ This-> cheque ();  / ** * Download de momenteel geverifieerde gebruiker. * * @return \ Illuminate \ Contracts \ Auth \ Authenticatable | null * / public function user () if (! is_null ($ this-> user)) return $ this-> user;  / ** * Haal de JSON params uit de huidige aanvraag * * @return string * / public function getJsonParams () $ jsondata = $ this-> request-> query ('jsondata'); return (! empty ($ jsondata)? json_decode ($ jsondata, TRUE): NULL);  / ** * Haal de ID op voor de huidige geverifieerde gebruiker. * * @return string | null * / public function id () if ($ user = $ this-> user ()) return $ this-> user () -> getAuthIdentifier ();  / ** * Valideer de referenties van een gebruiker. * * @return bool * / public function validate (Array $ credentials = []) if (empty ($ credentials ['username']) || empty ($ credentials ['password'])) if (! $ credentials = $ this-> getJsonParams ()) return false;  $ user = $ this-> provider-> retrievalByCredentials ($ credentials); if (! is_null ($ user) && $ this-> provider-> validateCredentials ($ user, $ credentials)) $ this-> setUser ($ user); geef waar terug;  else return false;  / ** * Stel de huidige gebruiker in. * * @param Array $ user Gebruikersinfo * @return void * / public function setUser (Authenticatable $ user) $ this-> user = $ user; stuur $ dit terug; 

Allereerst moet onze klas het Verlichten \ contracten \ Auth \ Guard interface. We moeten dus alle methoden definiëren die in die interface zijn gedeclareerd.

Het belangrijkste om op te merken is dat het __construct functie vereist een implementatie van Verlichten \ contracten \ Auth \ UserProvider. In ons geval geven we een exemplaar van App \ Extensions \ MongoUserProvider, zoals we in het volgende gedeelte zullen zien.

Vervolgens is er een functie getJsonParams die de gebruikersreferenties ophaalt uit de genoemde verzoekparameter jsondata. Omdat we verwachten dat we een JSON-gecodeerde reeks van gebruikersreferenties ontvangen, hebben we de json_decode functie om de JSON-gegevens te decoderen.

In de validatiefunctie is het eerste dat we controleren het bestaan ​​van de $ credentials argument. Als het niet aanwezig is, bellen we het getJsonParams methode om gebruikersreferenties op te halen uit de verzoekparameters.

Vervolgens noemen we de retrieveByCredentials methode van de MongoUserProvider provider die de gebruiker terughaalt uit de backend van de MongoDB-database. Eindelijk is het de validateCredentials methode van de MongoUserProvider aanbieder die de geldigheid van de gebruiker controleert.

Dus dat was de implementatie van onze aangepaste bewaker. In de volgende sectie wordt beschreven hoe u deze stukjes samenvoegt tot een succesvol verificatiesysteem.

Alles samenvoegen

Tot nu toe hebben we alle elementen van de aangepaste authenticatiebescherming ontwikkeld die ons een nieuw verificatiesysteem zou moeten bieden. Het zal echter niet uit de doos werken, omdat we het in de eerste plaats moeten registreren met behulp van de Laravel-servicecontainerverbindingen.

Zoals u al weet, is de Laravel-serviceprovider de juiste plaats om de benodigde bindingen te implementeren.

Ga je gang en open het bestand app / Providers / AuthServiceProvider.php waarmee we bindingsprocedures voor de verificatieservice kunnen toevoegen. Als het geen aangepaste wijzigingen bevat, kunt u het gewoon vervangen door de volgende inhoud.

 'App \ Policies \ ModelPolicy',]; / ** * Verificatie- / autorisatiediensten registreren. * * @return void * / public function boot () $ this-> registerPolicies (); $ this-> app-> bind ('App \ Database \ MongoDatabase', functie ($ app) plaats nieuwe MongoDatabase (config ('mongo.defaults.host'), config ('mongo.defaults.port'), config ('mongo.defaults.database'));); $ this-> app-> bind ('App \ Models \ Auth \ User', functie ($ app) retourneer nieuwe gebruiker ($ app-> make ('App \ Database \ MongoDatabase'));); // voeg aangepaste bewakingsprovider toe Auth :: provider ('mongo', functie ($ app, array $ config) retourneer nieuwe MongoUserProvider ($ app-> make ('App \ Models \ Auth \ User'));); // voeg custom guard toe Auth :: extend ('json', function ($ app, $ name, array $ config) retourneer nieuwe JsonGuard (Auth :: createUserProvider ($ config ['provider']), $ app-> make ('verzoek')); );  public function register () $ this-> app-> bind ('App \ Services \ Contracts \ NosqlServiceInterface', 'App \ Database \ MongoDatabase'); 

Laten we door de bagageruimte methode die de meeste providerbindingen bevat.

Om te beginnen maken we bindingen voor de App \ Database \ MongoDatabase en App \ Models \ Auth \ User elementen.

$ this-> app-> bind ('App \ Database \ MongoDatabase', functie ($ app) plaats nieuwe MongoDatabase (config ('mongo.defaults.host'), config ('mongo.defaults.port'), config ('mongo.defaults.database'));); $ this-> app-> bind ('App \ Models \ Auth \ User', functie ($ app) retourneer nieuwe gebruiker ($ app-> make ('App \ Database \ MongoDatabase')););

Het is een tijdje geleden dat we het hadden over provider en bewaker, en het is tijd om onze aangepaste bewaking in te pluggen in het Laravel-authenticatiesysteem.

We hebben de providermethode van de Auth Facade om onze aangepaste authenticatieprovider onder de sleutel toe te voegen mongo. Herinner dat de sleutel de instellingen weerspiegelt die eerder in de auth.php het dossier.

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

Op een vergelijkbare manier injecteren we onze aangepaste bewakingsimplementatie met behulp van de methode extend van de Auth facade.

Auth :: extend ('json', functie ($ app, $ naam, array $ config) retourneer nieuwe JsonGuard (Auth :: createUserProvider ($ config ['provider']), $ app-> make ('request') ););

Vervolgens is er een registreren methode die we hebben gebruikt om het te binden App \ Services \ contracten \ NosqlServiceInterface interface met de App \ Database \ MongoDatabase implementatie.

$ this-> app-> bind ('App \ Services \ Contracts \ NosqlServiceInterface', 'App \ Database \ MongoDatabase');

Dus wanneer het nodig is om het probleem op te lossen App \ Services \ contracten \ NosqlServiceInterface afhankelijkheid, Laravel antwoordt met de implementatie van de App \ Database \ MongoDatabase adapter.

Het voordeel van het gebruik van deze methode is dat men de gegeven implementatie gemakkelijk kan omwisselen met een aangepaste implementatie. Laten we bijvoorbeeld zeggen dat iemand de App \ Database \ MongoDatabase implementatie met de CouchDB-adapter in de toekomst. In dat geval hoeven ze alleen de bijbehorende binding toe te voegen aan de registermethode.

Dus dat was de dienstverlener tot uw beschikking. Op dit moment hebben we alles wat nodig is om onze aangepaste bewakingsimplementatie te testen, dus het volgende en afsluitende gedeelte gaat daar allemaal over.

Werkt het?

Je hebt al het harde werk gedaan om je eerste aangepaste authenticatiebewaker in te stellen, en nu is het tijd om de voordelen te plukken, want we gaan het maar proberen.

Laten we snel een vrij eenvoudig controllerbestand implementeren app / Http / Controllers / MongoController.php zoals hieronder getoond.

validate ()) // haal de huidige geverifieerde gebruiker $ user = $ auth_guard-> user (); echo 'Succes!';  else echo 'Geen toestemming om deze pagina te openen!'; 

Kijk goed naar de afhankelijkheid van de inlogmethode, waarvoor de implementatie van de Verlichten \ contracten \ Auth \ Guard guard. Omdat we de gewoonte bewaker als de standaard bewaker in de auth.php bestand, het is de App \ Services \ Auth \ JsonGuard dat zal daadwerkelijk worden geïnjecteerd!

Vervolgens hebben we het bevestigen methode van de App \ Services \ Auth \ JsonGuard klasse, die op zijn beurt een reeks methodeaanroepen initieert:

  • Het roept de retrieveByCredentials methode van de App \ Extensions \ MongoUserProvider klasse.
  • De retrieveByCredentials methode noemt het fetchUserByCredentials methode van de gebruiker App \ Models \ Auth \ User klasse.
  • De fetchUserByCredentials methode noemt het vind methode van de App \ Database \ MongoDatabase om de gebruikersreferenties op te halen.
  • eindelijk, de vind methode van de App \ Database \ MongoDatabase geeft het antwoord terug!

Als alles werkt zoals verwacht, zouden we een geverifieerde gebruiker moeten krijgen door het gebruiker methode van onze bewaker.

Om toegang te krijgen tot de controller, moet u een geassocieerde route toevoegen in de routes / web.php het dossier.

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

Probeer toegang te krijgen tot de URL http: // uw-laravel-site / aangepast / mongo / login zonder parameters door te geven en u zou een "niet geautoriseerd" bericht moeten zien.

Aan de andere kant, probeer iets als http: // uw-laravel-site / aangepast / mongo / login? Jsondata = "gebruikersnaam": "admin", "wachtwoord": "admin" en dat zou een succesboodschap moeten teruggeven als de gebruiker aanwezig is in uw database.

Let op: dit is slechts een voorbeeld, om te laten zien hoe de aangepaste bewaker werkt. U moet een waterdichte oplossing implementeren voor een functie zoals inloggen. Ik heb zelfs zojuist inzicht gegeven in de authenticatiestroom; u bent verantwoordelijk voor het bouwen van een robuuste en veilige oplossing voor uw toepassing.

Dat is onze reis vandaag en hopelijk ben ik terug met meer nuttige dingen. Als je wilt dat ik over specifieke onderwerpen schrijf, vergeet dan niet om me een bericht te sturen!

Conclusie

Het Laravel-framework biedt een solide authenticatiesysteem in de kern dat kan worden uitgebreid als u een aangepast systeem wilt implementeren. Dat was het onderwerp van het artikel van vandaag om een ​​aangepaste bewaker te implementeren en deze aan te sluiten op de Laravel-authenticatieworkflow.

In de loop daarvan hebben we een systeem ontwikkeld dat de gebruiker verifieert op basis van de JSON-payload in het verzoek en overeenkomt met de MongoDB-database. En om dat te bereiken, hebben we uiteindelijk een aangepaste bewaker en een aangepaste provider-implementatie gemaakt.

Ik hoop dat de oefening je inzicht heeft gegeven in de Laravel-authenticatiestroom, en je zou nu meer zelfvertrouwen moeten hebben over zijn innerlijke werking.

Voor degenen onder u die net zijn begonnen met Laravel of die op zoek zijn om uw kennis, site of applicatie uit te breiden met uitbreidingen, hebben wij een aantal dingen die u kunt bestuderen op Envato Market.

Ik zou graag uw feedback en suggesties horen, dus schreeuw hardop met behulp van de onderstaande feed!