Hoe gebruikersauthenticatie uit te voeren met de Symfony-beveiligingscomponent

In dit artikel leert u hoe u gebruikersverificatie instelt in PHP met behulp van de Symfony-beveiligingscomponent. Naast authenticatie zal ik u laten zien hoe u de rolgebaseerde autorisatie gebruikt, die u kunt uitbreiden op basis van uw behoeften.

De Symfony-beveiligingscomponent

Met de Symfony-beveiligingscomponent kunt u zeer eenvoudig beveiligingsfuncties instellen zoals verificatie, op rollen gebaseerde autorisatie, CSRF-tokens en meer. In feite is het verder onderverdeeld in vier subcomponenten waaruit u kunt kiezen op basis van uw behoeften.

De beveiligingscomponent heeft de volgende subcomponenten:

  • symfony / security-core
  • symfony / security-http
  • symfony / security-csrf
  • symfony / security-ACL

In dit artikel gaan we op zoek naar de authenticatiefunctie van de symfony / security-core bestanddeel.

Zoals gewoonlijk beginnen we met de installatie- en configuratie-instructies, en vervolgens verkennen we enkele praktijkvoorbeelden om de belangrijkste concepten te demonstreren.

Installatie en configuratie

In deze sectie gaan we de Symfony Security-component installeren. Ik neem aan dat u Composer al op uw systeem hebt geïnstalleerd. We hebben het nodig om de beveiligingscomponent die beschikbaar is op Packagist te installeren.

Dus ga je gang en installeer de beveiligingscomponent met behulp van de volgende opdracht.

$ componist vereist symfony / veiligheid

We laden gebruikers uit de MySQL-database in ons voorbeeld, dus we hebben ook een database-abstractielaag nodig. Laten we een van de meest populaire database-abstractielagen installeren: Doctrine DBAL.

$ componist vereist doctrine / dbal

Dat zou de composer.json bestand, dat er als volgt uit moet zien:

"require": "symfony / security": "^ 4.1", "doctrine / dbal": "^ 2.7"

Laten we het aanpassen composer.json bestand om er als volgt uit te zien.

"require": "symfony / security": "^ 4.1", "doctrine / dbal": "^ 2.7", "autoload": "psr-4": "Sfauth \\": "src" , "classmap": ["src"]

Omdat we een nieuwe hebben toegevoegd classmap invoer, laten we doorgaan en de autoloader van de componist bijwerken door de volgende opdracht uit te voeren.

$ composer dump -o

Nu kunt u de Sfauth naamruimte om klassen autoload onder de src directory.

Dus dat is het installatiedeel, maar hoe moet je het gebruiken? In feite is het gewoon een kwestie van het opnemen van de autoload.php bestand gemaakt door Composer in uw toepassing, zoals getoond in het volgende fragment.

Een real-world voorbeeld

Laten we eerst de gebruikelijke authenticatiestroom doornemen die wordt geboden door de Symfony-beveiligingscomponent.

  • Het eerste is om de gebruikersreferenties op te halen en een niet-geverifieerd token aan te maken.
  • Vervolgens geven we een niet-geverifieerd token door aan de authenticatiemanager voor validatie.
  • De authenticatiemanager kan verschillende authenticatieproviders bevatten en een daarvan zal worden gebruikt om het huidige gebruikersverzoek te verifiëren. De logica van hoe de gebruiker wordt geverifieerd, wordt gedefinieerd in de verificatieprovider.
  • De authenticatieprovider neemt contact op met de gebruiker om de gebruiker op te halen. Het is de verantwoordelijkheid van de gebruiker om gebruikers te laden vanaf de respectieve back-end.
  • De gebruikersprovider probeert de gebruiker te laden met behulp van de legitimatiegegevens die door de verificatieprovider zijn verstrekt. In de meeste gevallen retourneert de gebruikersprovider het gebruikersobject dat de Gebruikersomgeving interface.
  • Als de gebruiker wordt gevonden, retourneert de verificatieprovider een niet-geverifieerd token en kunt u dit token opslaan voor de volgende verzoeken.

In ons voorbeeld gaan we de gebruikersreferenties vergelijken met de MySQL-database, dus we moeten de database-gebruikersprovider maken. We zullen ook de database-authenticatieprovider maken die de authenticatielogica verwerkt. En tot slot maken we de klasse User, die de. Implementeert Gebruikersomgeving interface.

De gebruikersklasse

In deze sectie maken we de klasse User die de gebruikersentiteit in het authenticatieproces vertegenwoordigt.

Ga je gang en maak de src / User / User.php bestand met de volgende inhoud.

gebruikersnaam = $ gebruikersnaam; $ this-> wachtwoord = $ wachtwoord; $ this-> roles = $ roles;  openbare functie getUsername () return $ this-> gebruikersnaam;  openbare functie getPassword () return $ this-> wachtwoord;  openbare functie getRoles () return explode (",", $ this-> roles);  openbare functie getSalt () return "; public function eraseCredentials () 

Het belangrijkste is dat de klasse User de Symfony Security moet implementeren Gebruikersomgeving interface. Afgezien daarvan is er hier niets bijzonders.

De databaseproviderklasse

Het is de verantwoordelijkheid van de gebruiker om gebruikers vanaf de back-end te laden. In deze sectie maken we de database-gebruikersprovider, die de gebruiker laadt vanuit de MySQL-database.

Laten we het maken src / User / DatabaseUserProvider.php bestand met de volgende inhoud.

verbinding = $ verbinding;  openbare functie loadUserByUsername ($ gebruikersnaam) return $ this-> getUser ($ gebruikersnaam);  private function getUser ($ gebruikersnaam) $ sql = "SELECT * FROM sf_users WHERE gebruikersnaam =: name"; $ stmt = $ this-> connection-> prepare ($ sql); $ stmt-> bindValue ("naam", $ gebruikersnaam); $ Stmt-> execute (); $ row = $ stmt-> fetch (); if (! $ row ['gebruikersnaam']) $ exception = new GebruikersnaamNotFoundException (sprintf ('Gebruikersnaam "% s" niet gevonden in de database.', $ row ['gebruikersnaam'])); $ Buitenge-> setUsername ($ username); $ uitzondering gooien;  else retourneer nieuwe gebruiker ($ rij ['gebruikersnaam'], $ rij ['wachtwoord'], $ rij ['rollen']);  public function refreshUser (UserInterface $ user) if (! $ user instanceof User) throw new UnsupportedUserException (sprintf ('Instances of "% s" worden niet ondersteund.', get_class ($ user)));  return $ this-> getUser ($ user-> getUsername ());  public function supportsClass ($ class) ga terug naar 'Sfauth \ User \ User' === $ class; 

De gebruikersprovider moet het UserProviderInterface interface. We gebruiken de doctrine DBAL om de database-gerelateerde bewerkingen uit te voeren. Zoals we de. Hebben geïmplementeerd UserProviderInterface interface, moeten we de loadUserByUsername, refreshUser, en supportsClass methoden.

De loadUserByUsername methode moet de gebruiker laden door de gebruikersnaam, en dat gebeurt in de getUser methode. Als de gebruiker wordt gevonden, retourneren we de bijbehorende Sfauth \ User \ User object, dat het Gebruikersomgeving interface.

Aan de andere kant, de refreshUser methode ververst de meegeleverde Gebruiker object door de nieuwste informatie uit de database op te halen.

En tot slot, de supportsClass methode controleert of de DatabaseUserProvider provider ondersteunt de geleverde gebruikersklasse.

De database-verificatieprovidersklasse

Ten slotte moeten we de provider voor gebruikersverificatie implementeren, die de authenticatielogica definieert - hoe een gebruiker wordt geverifieerd. In ons geval moeten we de gebruikersreferenties vergelijken met de MySQL-database en daarom moeten we de authenticatielogica dienovereenkomstig definiëren.

Ga je gang en maak de src / User / DatabaseAuthenticationProvider.php bestand met de volgende inhoud.

userProvider = $ userProvider;  beschermde functie retrieveUser ($ gebruikersnaam, GebruikersnaamPasswordToken $ token) $ user = $ token-> getUser (); if ($ user instanceof UserInterface) return $ user;  probeer $ user = $ this-> userProvider-> loadUserByUsername ($ gebruikersnaam); if (! $ user instanceof UserInterface) gooi nieuwe AuthenticationServiceException ('De gebruiker moet een UserInterface-object retourneren.');  return $ gebruiker;  catch (GebruikersnaamNotFoundException $ e) $ e-> setUsername ($ gebruikersnaam); werp $ e;  catch (\ Uitzondering $ e) $ e = nieuwe AuthenticationServiceException ($ e-> getMessage (), 0, $ e); $ E-> setToken ($ token); werp $ e;  beschermde functie checkAuthentication (UserInterface $ user, UsernamePasswordToken $ token) $ currentUser = $ token-> getUser (); if ($ currentUser instance of UserInterface) if ($ currentUser-> getPassword ()! == $ user-> getPassword ()) gooi nieuwe AuthenticationException ('Referenties zijn gewijzigd van een andere sessie.');  else $ password = $ token-> getCredentials (); if (empty ($ password)) throw new AuthenticationException ('Wachtwoord mag niet leeg zijn');  if ($ user-> getPassword ()! = md5 ($ wachtwoord)) gooi nieuwe AuthenticationException ('Wachtwoord is ongeldig.'); 

De DatabaseAuthenticationProvider authenticatie provider breidt het UserAuthenticationProvider abstracte klasse. Daarom moeten we het retrieveUser en checkAuthentication abstracte methoden.

De taak van de retrieveUser methode is om de gebruiker te laden van de bijbehorende gebruikersprovider. In ons geval gebruikt het de DatabaseUserProvider gebruikersprovider om de gebruiker vanuit de MySQL-database te laden.

Aan de andere kant, de checkAuthentication methode voert de nodige controles uit om de huidige gebruiker te verifiëren. Houd er rekening mee dat ik de MD5-methode heb gebruikt voor wachtwoordversleuteling. U moet natuurlijk veiligere versleutelingsmethoden gebruiken om gebruikerswachtwoorden op te slaan.

Hoe het werkt Alles samen

Tot dusverre hebben we alle noodzakelijke elementen voor authenticatie gecreëerd. In deze sectie zullen we zien hoe we alles samen kunnen stellen om de authenticatiefunctionaliteit in te stellen.

Ga je gang en maak de db_auth.php bestand en vul het met de volgende inhoud.

 'mysql: // USERNAME: PASSWORD @ HOSTNAME / DATABASE_NAME'), new \ Doctrine \ DBAL \ Configuration ()); // start onze aangepaste db-gebruikersprovider $ userProvider = new DatabaseUserProvider ($ doctrineConnection); // we zullen standaard UserChecker gebruiken, het wordt gebruikt om extra controles te controleren, zoals accountvergrendeling / verlopen enz. // u kunt uw eigen controles uitvoeren door UserCheckerInterface-interface te implementeren $ userChecker = new UserChecker (); // start onze aangepaste db-authenticatieprovider $ dbProvider = new DatabaseAuthenticationProvider ($ userProvider, $ userChecker, 'frontend'); // init authentication provider manager $ authenticationManager = nieuwe AuthenticationProviderManager (array ($ dbProvider)); probeer // init un / pw, meestal krijg je deze van de variabele $ _POST, ingediend door de eindgebruiker $ username = 'admin'; $ wachtwoord = 'admin'; // ontvang niet-geverifieerd token $ unauthenticatedToken = new UsernamePasswordToken ($ gebruikersnaam, $ wachtwoord, 'frontend'); // authenticate user & get authenticated token $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken); // we hebben het geverifieerde token (gebruiker is nu ingelogd), het kan worden opgeslagen in een sessie voor later gebruik echo $ authenticatedToken; echo "\ n";  catch (AuthenticationException $ e) echo $ e-> getMessage (); echo "\ n"; 

Herinner de authenticatiestroom die aan het begin van dit artikel werd besproken - de bovenstaande code weerspiegelt die reeks.

Het eerste was om de gebruikersreferenties op te halen en een niet-geverifieerd token te maken.

$ unauthenticatedToken = new UsernamePasswordToken ($ gebruikersnaam, $ wachtwoord, 'frontend');

Vervolgens hebben we dat token doorgegeven aan de authenticatiemanager voor validatie.

// authenticate user & get authenticated token $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken);

Wanneer de authenticatiemethode wordt aangeroepen, gebeurt er een heleboel dingen achter de schermen.

Ten eerste selecteert de authenticatiemanager een geschikte authenticatieprovider. In ons geval is het de DatabaseAuthenticationProvider authenticatieprovider, die zal worden geselecteerd voor authenticatie.

Vervolgens haalt het de gebruiker op door de gebruikersnaam van de DatabaseUserProvider gebruiker. eindelijk, de checkAuthentication methode voert de nodige controles uit om het huidige gebruikersverzoek te verifiëren.

Als u de. Wilt testen db_auth.php script, moet u het maken sf_users tabel in uw MySQL-database.

MAAK TAFEL 'sf_users' ('id' int (11) NOT NULL AUTO_INCREMENT, 'gebruikersnaam' varchar (255) NOT NULL, 'wachtwoord' varchar (255) NOT NULL, 'rollen' enum ('registered', 'moderator', 'admin') DEFAULT NULL, PRIMARY KEY ('id')) MOTOR = InnoDB; INSERT IN 'sf_users' VALUES (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'admin');

Ga je gang en voer de db_auth.php script om te zien hoe het gaat. Na succesvolle voltooiing zou u een geverifieerd token moeten ontvangen, zoals getoond in het volgende fragment.

$ php db_auth.php UsernamePasswordToken (user = "admin", authenticated = true, roles = "admin")

Nadat de gebruiker is geverifieerd, kunt u het geverifieerde token in de sessie opslaan voor de volgende aanvragen.

En daarmee hebben we onze eenvoudige verificatiedemo voltooid!

Conclusie

Vandaag hebben we de component Symfony Security bekeken, waarmee u beveiligingsfuncties in uw PHP-toepassingen kunt integreren. We hebben specifiek gesproken over de authenticatiefunctie van de symfony / security-core subcomponent en ik heb je een voorbeeld laten zien van hoe deze functionaliteit kan worden geïmplementeerd in je eigen app.

Voel je vrij om je gedachten te posten met behulp van de onderstaande feed!