Cum se face autentificarea utilizatorului cu componenta de securitate Symfony

În acest articol, veți învăța cum să configurați autentificarea utilizatorilor în PHP utilizând componenta Symfony Security. Pe lângă autentificare, vă voi arăta cum să utilizați autorizarea bazată pe rol, pe care o puteți extinde în funcție de nevoile dvs..

Componenta de securitate Symfony

Componenta de securitate Symfony vă permite să configurați funcții de securitate precum autentificarea, autorizarea bazată pe roluri, jetoanele CSRF și mai ușor. De fapt, este în continuare împărțit în patru sub-componente pe care le puteți alege în funcție de nevoile dvs..

Componenta de securitate are următoarele subcomponente:

  • Symfony / securitate-core
  • Symfony / securitate http
  • Symfony / securitate CSRF
  • Symfony / securitate-acl

În acest articol, vom explora caracteristica de autentificare oferită de Symfony / securitate-core component.

Ca de obicei, vom începe cu instrucțiunile de instalare și configurare și apoi vom explora câteva exemple din lumea reală pentru a demonstra conceptele cheie.

Instalare și configurare

În această secțiune, vom instala componenta Symfony Security. Presupun că ați instalat deja Compozitor în sistemul dvs. - vom avea nevoie de el pentru a instala componenta de securitate disponibilă la Packagist.

Deci, mergeți mai departe și instalați componenta de securitate utilizând următoarea comandă.

Compozitorul $ necesită simfonie / securitate

Vom încărca utilizatorii din baza de date MySQL în exemplul nostru, deci avem nevoie și de un strat de abstractizare a bazei de date. Să instalați unul dintre cele mai populare straturi de abstractizare a bazei de date: Doctrină DBAL.

$ compozitorul cere doctrină / dbal

Ar fi trebuit să creeze composer.json fișier, care ar trebui să arate astfel:

"necesită": "symfony / security": "^ 4.1", "doctrine / dbal": "^ 2.7"

Să modificăm composer.json fișierul să arate ca unul următor.

"necesită": "simfony / security": "^ 4.1", "doctrine / dbal" , "classmap": ["src"]

Așa cum am adăugat un nou classmap intrare, să mergem mai departe și să actualizăm autoloaderul compozitorului executând următoarea comandă.

comisionul compozitorului $ -o

Acum, puteți folosi Sfauth spațiu de nume la clasele de autoreglare în cadrul src director.

Deci asta este partea de instalare, dar cum ar trebui să o folosești? De fapt, este doar o chestiune de a include autoload.php fișier creat de Compozitor în aplicația dvs., așa cum se arată în fragmentul următor.

Un exemplu în lumea reală

În primul rând, hai să trecem prin fluxul obișnuit de autentificare furnizat de componenta Symfony Security.

  • Primul lucru este să preluați acreditările utilizatorilor și să creați un jeton neautentificat.
  • Apoi, vom transmite un jeton neautentificat managerului de autentificare pentru validare.
  • Managerul de autentificare poate conține diferiți furnizori de autentificare și unul dintre aceștia va fi utilizat pentru autentificarea cererii curente de utilizator. Logica modului în care utilizatorul este autentificat este definită de furnizorul de autentificare.
  • Furnizorul de autentificare contactează furnizorul de servicii pentru a prelua utilizatorul. Este responsabilitatea utilizatorului de a încărca utilizatorii din back-end-ul respectiv.
  • Furnizorul de utilizator încearcă să încarce utilizatorul utilizând datele de identificare furnizate de furnizorul de autentificare. În majoritatea cazurilor, furnizorul de utilizator returnează obiectul utilizator care implementează Interfața cu utilizatorul interfață.
  • Dacă utilizatorul este găsit, furnizorul de autentificare returnează un jeton neautorizat și puteți stoca acest token pentru solicitările ulterioare.

În exemplul nostru, vom potrivi acreditările utilizatorului cu baza de date MySQL, astfel că va trebui să creați furnizorul de servicii de bază de date. De asemenea, vom crea furnizorul de autentificare a bazei de date care gestionează logica de autentificare. În final, vom crea clasa Utilizator, care implementează Interfața cu utilizatorul interfață.

Clasa utilizator

În această secțiune, vom crea clasa utilizator care reprezintă entitatea utilizatorului în procesul de autentificare.

Continuați și creați src / utilizator / User.php fișier cu următorul conținut.

username = $ username; $ this-> password = $ parola; $ this-> roles = $ roluri;  funcția publică getUsername () return $ this-> username;  funcția publică getPassword () return $ this-> password;  funcția publică getRoles () return explodează (",", $ this-> roles);  funcția publică getSalt () return "; funcția publică eraseCredentials () 

Lucrul important este că clasa utilizator trebuie să implementeze sistemul de securitate Symfony Interfața cu utilizatorul interfață. În afară de asta, nu e nimic neobișnuit aici.

Clasa furnizorului de baze de date

Este responsabilitatea furnizorului de a încărca utilizatorii din back-end. În această secțiune, vom crea furnizorul de baze de date, care îl încarcă pe utilizator din baza de date MySQL.

Să creăm src / utilizator / DatabaseUserProvider.php fișier cu următorul conținut.

conexiune = $ conexiune;  funcția publică loadUserByUsername ($ username) return $ this-> getUser ($ username);  funcția privată getUser ($ username) $ sql = "SELECT * FROM sf_users WHERE username =: nume"; $ stmt = $ this-> conexiune-> pregăti ($ sql); $ stmt-> bindValue ("nume", $ username); $ Stmt-> execute (); $ rând = $ stmt-> preluare (); dacă ! $ row ['username']) $ exception = new NumeNotFoundException (sprintf ("Utilizator"% s "nu a fost găsit în baza de date"; $ row ['username'])); $ Excepțional de> setUsername ($ username); arunca $ exception;  altfel returnează un utilizator nou ($ row ['username'], $ row ['password'], $ row ['roles']);  funcția publică refreshUser (UserInterface $ user) if ($ user instanceof User) arunca noul UnsupportedUserException (sprintf ('Instanțele lui "% s" nu sunt acceptate.  return $ this-> getUser ($ user-> getUsername ());  funcția publică supportsClass ($ class) returnează 'Sfauth \ User \ User' === $ class; 

Furnizorul de utilizator trebuie să implementeze UserProviderInterface interfață. Utilizăm doctrina DBAL pentru a efectua operațiile bazate pe bază de date. După cum am implementat UserProviderInterface interfață, trebuie să punem în aplicare loadUserByUsername, refreshUser, și supportsClass metode.

loadUserByUsername metoda ar trebui să încarce utilizatorul după numele de utilizator, și asta se face în getUser metodă. Dacă utilizatorul este găsit, returnează suma corespunzătoare Sfauth \ utilizator \ utilizator obiect, care implementează Interfața cu utilizatorul interfață.

Pe de altă parte, refreshUser metoda actualizează produsul furnizat Utilizator obiecte prin preluarea celor mai recente informații din baza de date.

Și, în final, supportsClass metoda verifică dacă DatabaseUserProvider furnizorul acceptă clasa de utilizatori furnizată.

Clasa de furnizori de autentificare a bazei de date

În cele din urmă, trebuie să implementăm furnizorul de autentificare a utilizatorului, care definește logica autentificării - modul în care un utilizator este autentificat. În cazul nostru, trebuie să se potrivească acreditările utilizatorului cu baza de date MySQL și, prin urmare, trebuie să definim logica de autentificare.

Continuați și creați src / utilizator / DatabaseAuthenticationProvider.php fișier cu următorul conținut.

userProvider = $ userProvider;  funcția protejată retrieveUser ($ username, UsernamePasswordToken $ token) $ user = $ token-> getUser (); dacă ($ user instanceof UserInterface) return $ user;  încercați $ user = $ this-> userProvider-> loadUserByUsername ($ username); if ($ user instanceof UserInterface) arunca noul AuthenticationServiceException ('Furnizorul de utilizator trebuie să returneze un obiect UserInterface.');  return $ user;  captură (NumeNotFoundExcepție $ e) $ e-> setUsername ($ username); arunca $ e;  captură (\ Excepție $ e) $ e = nouă AuthenticationServiceException ($ e-> getMessage (), 0, $ e); $ E> setToken ($ token); arunca $ e;  funcția protejată checkAuthentication (UserInterface $ user, NumePasswordToken $ token) $ currentUser = $ token-> getUser (); dacă ($ currentUser instanceof UserInterface) if ($ currentUser-> getPassword ()! == $ user-> getPassword ()) aruncați o nouă AuthenticationException ("Au fost schimbate acreditările dintr-o altă sesiune";  altceva $ password = $ token-> getCredentials (); if (empty ($ password)) arunca noua AuthenticationException ("Parola nu poate fi goala");  dacă ($ user-> getPassword ()! = md5 ($ password)) arunca noua AuthenticationException ("Parola nu este validă"); 

DatabaseAuthenticationProvider furnizorul de autentificare extinde UserAuthenticationProvider clasă abstractă. Prin urmare, trebuie să punem în aplicare retrieveUser și checkAuthentication metode abstracte.

Locul de muncă al retrieveUser metoda este de a încărca utilizatorul de la furnizorul de servicii corespunzător. În cazul nostru, va folosi DatabaseUserProvider utilizator pentru a încărca utilizatorul din baza de date MySQL.

Pe de altă parte, checkAuthentication metoda efectuează verificările necesare pentru autentificarea utilizatorului curent. Rețineți că am folosit metoda MD5 pentru criptarea parolei. Desigur, ar trebui să utilizați metode de criptare mai sigure pentru a stoca parolele utilizatorilor.

Cum funcționează în totalitate

Până acum, am creat toate elementele necesare autentificării. În această secțiune, vom vedea cum să le punem împreună pentru a configura funcția de autentificare.

Continuați și creați db_auth.php fișier și o populează cu următorul conținut.

 'mysql: // USERNAME: PASSWORD @ HOSTNAME / DATABASE_NAME'), noul \ Doctrine \ DBAL \ Configuration ()); // init furnizorul de servicii custom db $ userProvider = new DatabaseUserProvider ($ doctrineConnection); // vom folosi UserChecker implicit, este folosit pentru a verifica verificări suplimentare cum ar fi blocarea contului / expirat etc. // puteți implementa propria dvs. prin implementarea interfeței UserCheckerInterface $ userChecker = nou UserChecker (); // init furnizorul nostru de autentificare db personalizat $ dbProvider = new DatabaseAuthenticationProvider ($ userProvider, $ userChecker, 'frontend'); // administrator de autentificare de autentificare init $ authenticationManager = new AuthenticationProviderManager (array ($ dbProvider)); încercați // init un / pw, de obicei le veți primi din variabila $ _POST, trimisă de utilizatorul final $ username = 'admin'; $ password = 'admin'; // a obține tokenul neautentificat $ unauthenticatedToken = noul UsernamePasswordToken ($ username, $ password, 'frontend'); // autentificați utilizatorul și obțineți jeton autentificat $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken); // am primit jetonul autentificat (utilizatorul este conectat acum), poate fi stocat într-o sesiune pentru o utilizare ulterioară echo $ authenticatedToken; echo "\ n";  captură (AuthenticationException $ e) echo $ e-> getMessage (); echo "\ n"; 

Amintiți-vă fluxul de autentificare care a fost discutat la începutul acestui articol - codul de mai sus reflectă acea secvență.

Primul lucru a fost să preluați acreditările utilizatorilor și să creați un jeton neautentificat.

$ unauthenticatedToken = nume de utilizator nouPasswordToken ($ username, $ password, 'frontend');

Apoi, am trecut acel jeton la managerul de autentificare pentru validare.

// autentificați utilizatorul și obțineți jeton autentificat $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken);

Când se numește metoda de autentificare, multe lucruri se întâmplă în spatele scenei.

În primul rând, managerul de autentificare selectează un furnizor de autentificare adecvat. În cazul nostru, este vorba de DatabaseAuthenticationProvider furnizor de autentificare, care va fi selectat pentru autentificare.

Apoi, utilizatorul recuperează numele de utilizator din DatabaseUserProvider utilizator. În cele din urmă, checkAuthentication metoda efectuează verificările necesare pentru autentificarea cererii curente de utilizator.

Dacă doriți să testați db_auth.php script, va trebui să creați sf_users tabel în baza de date MySQL.

CREATE TABLE 'sf_users' ('id' int (11) NOT NULL AUTO_INCREMENT, 'username' varchar (255) NOT NULL, 'parola' varchar (255) NOT NULL, 'admin') DEFAULT NULL, KEY PRIMARY ('id')) MOTOR = InnoDB; INSCRIEȚI ÎN VALORILE "sf_users" (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'admin');

Mergeți și conduceți db_auth.php script pentru a vedea cum merge. După finalizarea cu succes, ar trebui să primiți un token autentificat, așa cum se arată în fragmentul următor.

$ php db_auth.php Nume utilizatorPasswordToken (user = "admin", autentificat = true, roluri = "admin")

Odată ce utilizatorul este autentificat, puteți stoca tokenul autentificat în sesiune pentru solicitările ulterioare.

Și cu asta, am finalizat demo-ul nostru simplu de autentificare!

Concluzie

Astăzi, am analizat componenta Symfony Security, care vă permite să integrați caracteristicile de securitate în aplicațiile dvs. PHP. Mai exact, am discutat despre caracteristica de autentificare furnizată de subcomponenta simfony / security-core și am arătat un exemplu despre modul în care această funcționalitate poate fi implementată în propria dvs. aplicație.

Simțiți-vă liber să vă postați gândurile folosind feed-ul de mai jos!

Cod