Cum se creează o Gardă de autentificare personalizată în Laravel

În acest articol, vom acoperi sistemul de autentificare în cadrul Laravel. Scopul principal al acestui articol este de a crea o gardă de autentificare personalizată prin extinderea sistemului de autentificare de bază.

Laravel oferă un sistem solid de autentificare în bază, care face ca implementarea autentificării de bază să fie o briză. De fapt, trebuie doar să rulați câteva comenzi artizanale pentru a configura schela unui sistem de autentificare.

Mai mult decât atât, sistemul în sine este proiectat în așa fel încât să îl puteți extinde și să conectați adaptoarele personalizate de autentificare. Asta vom discuta în detaliu în cadrul acestui articol. Înainte de a merge mai departe și de a se arunca cu capul în punerea în aplicare a pazei de autentificare personalizate, vom începe cu o discuție despre elementele de bază din sistemul de autentificare Laravel-paznici și furnizori.

Elementele de bază: gardieni și furnizori

Sistemul de autentificare Laravel este alcătuit din două elemente la gărzile și furnizorii săi.

Gărzile

Ați putea să vă gândiți la un gardian ca pe o modalitate de a furniza logica utilizată pentru a identifica utilizatorii autentificați. În esență, Laravel oferă diferite gărzi cum ar fi sesiunea și jetonul. Securitatea sesiunii păstrează starea utilizatorului în fiecare solicitare prin cookie-uri, iar pe de altă parte protecția tokenului autentifică utilizatorul prin verificarea unui token valid la fiecare solicitare.

Deci, după cum puteți vedea, gardianul definește logica autentificării și nu este necesar ca aceasta să se ocupe întotdeauna de aceasta prin preluarea acreditărilor valide din spate. Puteți implementa un gardian care verifică pur și simplu prezența unui anumit lucru în anteturile de solicitare și autentifică utilizatorii pe baza acestuia.

Mai târziu, în acest articol, vom implementa un gardian care verifică anumiți parametri JSON în antetele de solicitare și va prelua utilizatorul valid din partea din spate MongoDB.

Furnizori

Dacă gardianul definește logica autentificării, furnizorul de autentificare este responsabil pentru recuperarea utilizatorului din spațiul de stocare din spate. Dacă gardianul cere ca utilizatorul să fie validat față de spațiul de back-end atunci implementarea de preluare a utilizatorului intră în furnizorul de autentificare.

Laravel navează cu doi furnizori de autentificare implicit - Bază de date și Elocvent. Furnizorul de autentificare a bazei de date se ocupă de recuperarea directă a acreditărilor utilizatorilor din spațiul de stocare din spate, în timp ce Eloquent oferă un strat de abstractizare care face necesarul.

În exemplul nostru, vom implementa un furnizor de autentificare MongoDB care va prelua acreditările utilizatorilor din MongoDB back end.

Aceasta a fost o introducere de bază a gardienilor și a furnizorilor din sistemul de autentificare Laravel. Din următoarea secțiune, ne vom concentra asupra dezvoltării agentului de protecție și a furnizorului de autentificare personalizată!

O scurtă privire la configurarea fișierului

Să aruncăm o privire rapidă asupra listei de fișiere pe care o vom implementa pe tot parcursul acestui articol.

  • config / auth.php: Este fișierul de configurare a autentificării în care vom adăuga o intrare a pazei personalizate.
  • config / mongo.php: Este fișierul care deține configurația MongoDB.
  • app / Servicii / Contracte / NosqlServiceInterface.php: Este o interfață implementată de clasa bazei de date personalizate Mongo.
  • app / Baza de date / MongoDatabase.php: Este o clasă principală de baze de date care interacționează cu MongoDB.
  • app / Modele / Aut / User.php: Este clasa de modele utilizator care implementează contractul Authenticable.
  • app / Extensii / MongoUserProvider.php: Este o implementare a furnizorului de autentificare.
  • app / Servicii / Aut / JsonGuard.php: Este o implementare a șoferului de autentificare.
  • app / Furnizori / AuthServiceProvider.php: Acesta este un fișier existent pe care îl vom folosi pentru a adăuga legăturile noastre pentru contacte de serviciu.
  • app / HTTP / Controllers / MongoController.php: Este un fișier de controler demo pe care îl vom implementa pentru a testa paza noastră personalizată.

Nu vă faceți griji dacă lista fișierelor nu are prea mult sens, deoarece vom discuta totul în detaliu pe măsură ce vom trece prin ea.

Deplasare profundă în implementare

În această secțiune, vom trece prin implementarea fișierelor necesare.

Primul lucru pe care trebuie să-l facem este să îl informăm pe Laravel despre gărzile noastre personalizate. Mergeți mai departe și introduceți detaliile de gardă personalizată în config / auth.php fișier așa cum este arătat.

... '=' ['driver' => 'sessions', 'provider' => 'users', ' '=>' utilizatori ',' custom '=> [' driver '=>' json ',' provider '=>' mongo ',],], ... 

După cum puteți vedea, am adăugat paza noastră personalizată sub personalizat cheie.

Apoi, trebuie să adăugăm o intrare asociată furnizorului în furnizorii de secțiune.

... 'furnizori' => ['utilizatori' => ['driver' => 'eloquent', 'model' => App \ User :: class, ], // 'utilizatori' => [// 'driver' => 'baza de date', // 'table' => 'utilizatori', //],], ... 

Am adăugat intrarea furnizorului nostru sub Mongo cheie.

În cele din urmă, să schimbăm protecția de autentificare implicită de la web la personalizat.

... 'defaults' => ['guard' => 'custom', 'passwords' => 'utilizatori',], ... 

Desigur, aceasta nu va funcționa încă, deoarece nu am implementat încă fișierele necesare. Și asta vom discuta în următoarele două secțiuni.

Configurați driverul MongoDB

În această secțiune, vom implementa fișierele necesare care vorbesc cu instanța MongoDB care stă la baza.

Să creați mai întâi un fișier de configurare config / mongo.php care deține setările implicite pentru conexiunea MongoDB.

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

Desigur, trebuie să modificați valorile substituentului conform setărilor.

În loc să creați direct o clasă care interacționează cu MongoDB, vom crea o interfață în primul rând.

Beneficiul creării unei interfețe este că oferă un contract pe care trebuie să îl respecte un dezvoltator în timp ce îl implementează. De asemenea, implementarea noastră de MongoDB ar putea fi ușor schimbată cu o altă implementare NoSQL dacă este necesar.

Mergeți mai departe și creați un fișier de interfață app / Servicii / Contracte / NosqlServiceInterface.php cu următorul conținut.

Este o interfață destul de simplă care declară metodele CRUD de bază pe care trebuie să le definească o clasă care implementează această interfață.

Acum, să definim o clasă reală la app / Baza de date / MongoDatabase.php.

conexiune = nou MongoClient ("mongodb: // $ host: $ port"); $ this-> database = $ this-> conexiune -> $ database;  / ** * @ se vede \ App \ Services \ Contracte \ NosqlServiceInterface :: find () * / find function ($ collect, Array $ criteria) $ criterii);  funcția publică crează ($ collection, Array $ document)  actualizare funcția publică ($ collection, $ id, Array $ document)  funcția publică șterge ($ collection, $ id) 

Desigur, presupun că ați instalat MongoDB și extensia corespunzătoare MongoDB PHP.

__construi metoda instanțiată MongoClient clasa cu parametrii necesari. Cealaltă metodă importantă de care suntem interesați este găsi care recuperează înregistrarea pe baza criteriilor furnizate ca argumente de metodă.

Așa a fost implementarea șoferului MongoDB și am încercat să o țin cât mai simplu posibil.

Configurați modelul de utilizator

Respectând standardele sistemului de autentificare, trebuie să implementăm modelul de utilizator care trebuie să implementeze Illuminate \ Contracte \ Auth \ Authenticatable contracta.

Continuați și creați un fișier app / Modele / Aut / User.php cu următorul conținut.

conn = $ conn;  / ** * Fetch utilizator prin credentiale * * @param array $ credentials * @return Iluminare \ Contracte \ Auth \ Authenticatable * / funcția publică fetchUserByCredentials (Array $ credentials) $ arr_user = $ this-> conn-> utilizatori ', [' username '=> $ credentials [' username ']]); dacă (! is_null ($ arr_user)) $ this-> username = $ arr_user ['username']; $ this-> parola = $ arr_user ['parola'];  returnați $ this;  / ** * @inheritDoc * se vede \ Illuminate \ Contracte \ Auth \ Authenticatable :: getAuthIdentifierName () * / funcția publică getAuthIdentifierName () return "username";  / ** * @inheritDoc * * vezi \ Illuminate \ Contracts \ Auth \ Authenticatable :: getAuthIdentifier () * / funcția publică getAuthIdentifier () return $ this -> $ this-> getAuthIdentifierName ();  / ** * @inheritDoc * se vede \ Illuminate \ Contracte \ Auth \ Authenticatable :: getAuthPassword () * / funcția publică getAuthPassword () return $ this-> password;  / ** * @inheritDoc * * se vede \ Illuminate \ Contracte \ Auth \ Authenticatable :: getRememberToken () * / funcția publică getRememberToken () if (! empty ($ this-> getRememberTokenName acest lucru -> $ this-> getRememberTokenName ();  / ** * @inheritDoc * observa \ Illuminate \ Contracte \ Auth \ Authenticatable :: setRememberToken () * / set publicRememberToken ($ value) if (! $ acest -> $ this-> getRememberTokenName () = valoarea $;  / ** * @inheritDoc * Se vede \ Illuminate \ Contracte \ Auth \ Authenticatable :: getRememberTokenName () * / funcția publică getRememberTokenName () return $ this-> rememberTokenName; 

Trebuia să fi observat deja asta App \ Modele \ Auth \ utilizator implementează Illuminate \ Contracte \ Auth \ Authenticatable contracta.

Cele mai multe dintre metodele implementate în clasa noastră sunt explicative. După ce am spus asta, am definit fetchUserByCredentials care recuperează utilizatorul din capătul din spate disponibil. În cazul nostru, va fi a MongoDatabase clasa care va fi chemată pentru a prelua informațiile necesare.

Deci, asta este implementarea modelului Utilizator.

Configurați furnizorul de autentificare

După cum am discutat mai devreme, sistemul de autentificare Laravel constă din două elemente de pază și furnizori.

În această secțiune, vom crea un furnizor de autentificare care se ocupă de recuperarea utilizatorului din spate.

Continuați și creați un fișier app / Extensii / MongoUserProvider.php așa cum se arată mai jos.

model = $ userModel;  / ** * Returnați un utilizator prin acreditările date. * * @param array $ credentials * @ return \ Illuminate \ Contracte \ Auth \ Authenticatable | null * / funcția publică retrieveByCredentials (array $ credentials) if (empty ($ credentials)) return;  $ user = $ this-> model-> fetchUserByCredentials (['username' => $ credentials ['username']]); return $ user;  / ** * Validarea unui utilizator împotriva acreditărilor date. * * @param \ Illuminate \ Contracts \ Auth \ Authenticatable $ user * @param array $ credentials Solicitări de acreditare * @return bool * / funcția publică validateCredentials (Authenticatable $ user, Array $ credentials) return ($ credentials ['username'] == $ user-> getAuthIdentifier () && md5 ($ credentials ['parola']) == $ user-> getAuthPassword ());  funcția publică retrieveById ($ identifier) ​​ funcția publică retrieveByToken ($ identifier, $ token)  public funcția updateRememberToken (Authenticatable $ user, $ token) 

Din nou, trebuie să vă asigurați că furnizorul personalizat trebuie să implementeze Illuminate \ Contracte \ Auth \ UserProvider contracta.

Deplasându-se în față, aceasta definește două metode importante - retrieveByCredentials și validateCredentials.

retrieveByCredentials metoda este utilizată pentru a prelua acreditările utilizatorilor utilizând clasa de modele utilizator care a fost discutată în secțiunea anterioară. Pe de altă parte, validateCredentials metoda este utilizată pentru a valida un utilizator împotriva setului de acreditări dat.

Și aceasta a fost implementarea furnizorului nostru de autentificare personalizat. În secțiunea următoare, vom merge mai departe și vom crea un gardian care să interacționeze cu MongoUserProvider furnizor de autentificare.

Configurați Garda de autentificare

Așa cum am discutat mai devreme, garda din sistemul de autentificare Laravel prevede modul în care utilizatorul este autentificat. În cazul nostru, vom verifica prezența jsondata cereți un parametru care să conțină șirul de caractere codificat JSON.

În această secțiune, vom crea un gardian care interacționează cu furnizorul de autentificare care tocmai a fost creat în ultima secțiune.

Continuați și creați un fișier app / Servicii / Aut / JsonGuard.php cu următorul conținut.

cerere = $ cerere; $ this-> provider = $ provider; $ this-> user = NULL;  / ** * Determinați dacă utilizatorul curent este autentificat. * * @return bool * / funcția de control public () return! is_null ($ this-> utilizator ());  / ** * Determinați dacă utilizatorul curent este invitat. * * @return bool * / public guest guest () return! $ This-> check ();  / ** * Obțineți utilizatorul autentificat în prezent. * @inturn \ Iluminare \ Contracte \ Auth \ Authenticatable | null * / user public function () if (! is_null ($ this-> user)) return $ this-> user;  / ** * Obțineți paramurile JSON din cererea curentă * * @return string * / funcția publică getJsonParams () $ jsondata = $ this-> request-> interogare ('jsondata'); retur (! gol ($ jsondata)? json_decode ($ jsondata, TRUE): NULL);  / ** * Obțineți ID-ul pentru utilizatorul autentificat în prezent. * * @ returnează șirul null * / id funcției publice () if ($ user = $ this-> user ()) return $ this-> user () -> getAuthIdentifier ();  / ** * Validarea acreditărilor unui utilizator. * * @return bool * / validare functie publica (Array $ credentials = []) daca (gol ($ credentials ['username']) || empty ($ credentials ['password' = $ this-> getJsonParams ()) return false;  $ user = $ this-> provider-> retrieveByCredentials ($ credentials); dacă (! is_null ($ user) && $ this-> provider-> validateCredentials ($ user, $ credentials)) $ this-> setUser ($ user); return true;  altfel return false;  / ** * Setați utilizatorul curent. * * @param Array $ user Informații utilizator * @return void * / public function setUser (Authenticatable $ user) $ this-> user = $ user; returnați $ this; 

În primul rând, clasa noastră trebuie să pună în aplicare Illuminate \ Contracte \ Auth \ Guard interfață. Astfel, trebuie să definim toate metodele declarate în acea interfață.

Cel mai important lucru pe care trebuie să-l observăm aici este faptul că __construi funcția necesită o punere în aplicare a Illuminate \ Contracte \ Auth \ UserProvider. În cazul nostru, vom trece un exemplu de App \ Extensii \ MongoUserProvider, după cum vom vedea în secțiunea următoare.

Apoi, există o funcție getJsonParams care preia acreditările utilizatorului din parametrul de cerere denumit jsondata. Deoarece se așteaptă să primim un șir JSON codificat de acreditările utilizatorului, am folosit json_decode pentru a decoda datele JSON.

În funcția de validare, primul lucru pe care îl verificăm este existența $ datele de conectare argument. Dacă nu este prezent, vom apela getJsonParams pentru a prelua acreditările utilizatorilor din parametrii de solicitare.

Apoi, numim retrieveByCredentials metodă a MongoUserProvider furnizor care recuperează utilizatorul din baza de date a bazei de date MongoDB. În cele din urmă, este validateCredentials metodă a MongoUserProvider furnizor care verifică validitatea utilizatorului.

Așa a fost și punerea în aplicare a pazei noastre personalizate. Următoarea secțiune descrie modul de cusătură a acestor piese împreună pentru a forma un sistem de autentificare cu succes.

Punându-le pe toți împreună

Până în prezent, am dezvoltat toate elementele sistemului de autentificare personalizat care ar trebui să ne ofere un nou sistem de autentificare. Cu toate acestea, nu va funcționa din cutie, deoarece trebuie să-l înregistrăm în primul rând folosind legăturile de container Laravel.

După cum ar trebui să știți, furnizorul de servicii Laravel este locul potrivit pentru a implementa legăturile necesare.

Continuați și deschideți fișierul app / Furnizori / AuthServiceProvider.php care ne permite să adăugăm legăturile pentru autentificarea containerelor de serviciu. Dacă nu conține modificări personalizate, le puteți înlocui cu următorul conținut.

 'Aplicații \ Politici \ ModelPolicy',]; / ** * Înregistrați orice servicii de autentificare / autorizare. * * @return void * / boot public funcția () $ this-> registerPolicies (); $ this-> app-> bind ('App \ Database \ MongoDatabase', funcția ($ app) return new MongoDatabase (config ('mongo.defaults.host'), config ("mongo.defaults.database"));); $ this-> app-> bind ("App \ Models \ Auth \ User", funcția ($ app) retur nou utilizator ($ app-> make ('App \ Database \ MongoDatabase')); // adăuga furnizorul de pază personalizat Auth :: provider ('mongo', funcția ($ app, array $ config) returnează noul MongoUserProvider ($ app-> make ('App \ Models \ Auth \ User')); // adăugați personalizat paza Auth :: extend ('json', funcția ($ app, $ name, array $ config) returnează noul JsonGuard ($ config ['provider']), $ app-> make ('cerere')); );  registrul funcțiilor publice () $ this-> app-> bind ('App \ Services \ Contracte \ NosqlServiceInterface', 'App \ Database \ MongoDatabase'); 

Să trecem prin cizmă care conține cea mai mare parte a legăturilor dintre furnizori.

Pentru a începe, vom crea legături pentru App \ Baza de date \ MongoDatabase și App \ Modele \ Auth \ utilizator element.

$ this-> app-> bind ('App \ Database \ MongoDatabase', funcția ($ app) return new MongoDatabase (config ('mongo.defaults.host'), config ("mongo.defaults.database"));); $ this-> app-> bind ("App \ Models \ Auth \ User", funcția ($ app) retur nou utilizator ($ app-> make ('App \ Database \ MongoDatabase'));

A trecut o vreme când am vorbit despre furnizor și gardian și este timpul să conectăm garda personalizată la sistemul de autentificare Laravel.

Am folosit metoda furnizorului Auth Fata pentru a adăuga furnizorul nostru de autentificare personalizată sub cheie Mongo. Rețineți că cheia reflectă setările adăugate anterior în auth.php fişier.

Auth :: furnizor ('mongo', funcția ($ app, array $ config) returnează noul MongoUserProvider ($ app-> make ('App \ Models \ Auth \ User'));

În mod similar, vom injecta implementarea personalizată a pazei folosind metoda extensie a metodei Auth faţadă.

Auth :: extend ('json', funcția ($ app, $ name, array $ config) returnează noul JsonGuard (Auth :: createUserProvider ($ config ['provider']), $ app-> make ););

Apoi, e a Inregistreaza-te metodă pe care am folosit-o pentru a le lega App \ Servicii \ Contracte \ NosqlServiceInterface interfață cu App \ Baza de date \ MongoDatabase punerea în aplicare.

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

Deci, ori de câte ori este nevoie să rezolvați problema App \ Servicii \ Contracte \ NosqlServiceInterface dependență, Laravel răspunde cu punerea în aplicare a App \ Baza de date \ MongoDatabase adaptor.

Beneficiul utilizării acestei abordări este că s-ar putea schimba cu ușurință implementarea dată printr-o implementare personalizată. De exemplu, să presupunem că cineva ar dori să înlocuiască App \ Baza de date \ MongoDatabase implementarea cu adaptorul CouchDB în viitor. În acest caz, trebuie doar să adăugați legarea corespunzătoare în metoda înregistrării.

Deci, acesta a fost furnizorul de servicii la dispoziția dumneavoastră. În acest moment, avem tot ce este necesar pentru a testa punerea în aplicare a pazei noastre personalizate, astfel încât secțiunea următoare și finală este totul despre asta.

Funcționează?

Ați făcut toată munca grea înființând prima dvs. gardă de autentificare personalizată și acum este timpul să profitați de avantajele pe care le vom face și vom încerca.

Să implementăm rapid un fișier destul de bază de controler app / HTTP / Controllers / MongoController.php așa cum se arată mai jos.

validați ()) // obțineți utilizatorul curent autentificat $ user = $ auth_guard-> user (); echo 'Success!';  altceva echo 'Nu este autorizat să acceseze această pagină!'; 

Uită-te atent la dependența metodei de autentificare, care necesită implementarea Illuminate \ Contracte \ Auth \ Guard paza. De când am setat personalizat pază ca gardă implicită în auth.php dosar, este App \ Services \ Auth \ JsonGuard care va fi injectat de fapt!

Apoi, am sunat valida metodă a App \ Services \ Auth \ JsonGuard clasa, care la rândul său inițiază o serie de apeluri metodice:

  • Se cheamă retrieveByCredentials metodă a App \ Extensii \ MongoUserProvider clasă.
  • retrieveByCredentials metoda solicită fetchUserByCredentials metoda Utilizatorului App \ Modele \ Auth \ utilizator clasă.
  • fetchUserByCredentials metoda solicită găsi metodă a App \ Baza de date \ MongoDatabase pentru a prelua acreditările utilizatorului.
  • În cele din urmă, găsi metodă a App \ Baza de date \ MongoDatabase returnează răspunsul!

Dacă totul funcționează așa cum era de așteptat, ar trebui să primim un utilizator autentificat sunând la utilizator metoda de gardă.

Pentru a accesa controlerul, trebuie să adăugați o rută asociată în rute / web.php fişier.

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

Încercați să accesați URL-ul http: // your-laravel-site / personalizat / mongo / login fără a trece nici un parametru și ar trebui să vedeți un mesaj "neautorizat".

Pe de altă parte, încercați ceva de genul http: // your-laravel-site / custom / mongo / login? Jsondata = "username": "admin", "password" dacă utilizatorul este prezent în baza dvs. de date.

Rețineți că acest lucru este doar pentru scopuri de exemplu, pentru a demonstra modul în care funcționează garda personalizată. Ar trebui să implementați o soluție sigură pentru o caracteristică precum login. De fapt, tocmai am oferit o perspectivă asupra fluxului de autentificare; sunteți responsabil pentru crearea unei soluții robuste și sigure pentru aplicația dvs..

Aceasta ne sfârșește astăzi călătoria și, sperăm, mă voi întoarce cu mai multe lucruri utile. Dacă vreți să scriu pe subiecte specifice, nu uitați să renunțați la o linie!

Concluzie

Cadrul Laravel oferă un sistem solid de autentificare în bază care ar putea fi extins dacă doriți să implementați unul personalizat. Acesta a fost subiectul articolului de astăzi de a implementa o gardă personalizată și conectați-o la fluxul de lucru de autentificare Laravel.

În acest sens, am continuat și am dezvoltat un sistem care autentifică utilizatorul bazat pe sarcina utilă JSON din cerere și îl potrivește cu baza de date MongoDB. Și pentru a realiza acest lucru, am ajuns să creăm o gardă personalizată și o implementare a furnizorului personalizat.

Sper că exercițiul vă oferă o perspectivă asupra fluxului de autentificare Laravel și acum ar trebui să vă simțiți mai încrezători în lucrările sale interioare.

Pentru cei care sunteți fie doar începători cu Laravel, fie căutați să vă extindeți cunoștințele, site-ul sau aplicația cu extensii, avem o varietate de lucruri pe care le puteți studia pe piața Envato.

Mi-ar plăcea să vă aud feedback și sugestii, așa că strigați cu voce tare folosind feed-ul de mai jos!

Cod