Come eseguire l'autenticazione utente con il componente di sicurezza Symfony

In questo articolo, imparerai come configurare l'autenticazione utente in PHP usando il componente Symfony Security. Oltre all'autenticazione, ti mostrerò come utilizzare la sua autorizzazione basata sui ruoli, che puoi estendere in base alle tue esigenze.

Il componente di sicurezza di Symfony

Symfony Security Component consente di configurare funzionalità di sicurezza come autenticazione, autorizzazione basata sui ruoli, token CSRF e molto più facilmente. Di fatto, è ulteriormente suddiviso in quattro sottocomponenti che puoi scegliere in base alle tue esigenze.

Il componente Sicurezza presenta le seguenti sottocomponenti:

  • symfony / sicurezza-core
  • symfony / sicurezza-http
  • symfony / sicurezza-CSRF
  • symfony / sicurezza-Acl

In questo articolo, esploreremo la funzione di autenticazione fornita da symfony / sicurezza-core componente.

Come al solito, inizieremo con le istruzioni di installazione e configurazione, quindi esamineremo alcuni esempi reali per dimostrare i concetti chiave.

Installazione e configurazione

In questa sezione, installeremo il componente Symfony Security. Presumo che tu abbia già installato Composer sul tuo sistema: ne avremo bisogno per installare il componente Security disponibile su Packagist.

Quindi, andare avanti e installare il componente di sicurezza utilizzando il seguente comando.

$ compositore richiede symfony / sicurezza

Nel nostro esempio caricheremo utenti dal database MySQL, quindi avremo anche bisogno di un livello di astrazione del database. Installiamo uno dei più popolari livelli di astrazione del database: Doctrine DBAL.

$ compositore richiede dottrina / dbal

Questo dovrebbe aver creato il composer.json file, che dovrebbe assomigliare a questo:

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

Modifichiamo il composer.json file per assomigliare al seguente.

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

Come abbiamo aggiunto un nuovo classmap voce, andiamo avanti e aggiorniamo il caricatore automatico del compositore eseguendo il seguente comando.

$ compositore discarica -o

Ora puoi usare il Sfauth spazio dei nomi per le classi di autoload sotto il src elenco.

Quindi questa è la parte di installazione, ma come si dovrebbe utilizzarla? In realtà, è solo questione di includere il autoload.php file creato da Composer nella tua applicazione, come mostrato nello snippet seguente.

Un esempio del mondo reale

Innanzitutto, passiamo attraverso il solito flusso di autenticazione fornito dal componente Symfony Security.

  • La prima cosa è recuperare le credenziali dell'utente e creare un token non autenticato.
  • Successivamente, passeremo un token non autenticato al gestore di autenticazione per la convalida.
  • Il gestore autenticazione può contenere diversi provider di autenticazione e uno di questi verrà utilizzato per autenticare la richiesta dell'utente corrente. La logica di come l'utente è autenticato è definita nel provider di autenticazione.
  • Il provider di autenticazione contatta il provider dell'utente per recuperare l'utente. È responsabilità del fornitore dell'utente caricare gli utenti dal rispettivo back-end.
  • Il provider dell'utente tenta di caricare l'utente utilizzando le credenziali fornite dal provider di autenticazione. Nella maggior parte dei casi, il provider dell'utente restituisce l'oggetto utente che implementa il file Interfaccia utente interfaccia.
  • Se l'utente viene trovato, il provider di autenticazione restituisce un token non autenticato ed è possibile memorizzare questo token per le richieste successive.

Nel nostro esempio, abbineremo le credenziali dell'utente al database MySQL, quindi dovremo creare il provider utente del database. Creeremo anche il provider di autenticazione del database che gestisce la logica di autenticazione. E infine, creeremo la classe User, che implementa il Interfaccia utente interfaccia.

La classe utente

In questa sezione creeremo la classe User che rappresenta l'entità utente nel processo di autenticazione.

Vai avanti e crea il src / utente / User.php file con il seguente contenuto.

username = $ username; $ this-> password = $ password; $ this-> roles = $ ruoli;  public function getUsername () return $ this-> username;  public function getPassword () return $ this-> password;  funzione pubblica getRoles () return explode (",", $ this-> roles);  public function getSalt () return "; public function eraseCredentials () 

L'importante è che la classe User debba implementare Symfony Security Interfaccia utente interfaccia. A parte questo, qui non c'è niente fuori dall'ordinario.

La classe del provider di database

È responsabilità del fornitore dell'utente caricare gli utenti dal back-end. In questa sezione creeremo il provider utente del database, che carica l'utente dal database MySQL.

Creiamo il src / utente / DatabaseUserProvider.php file con il seguente contenuto.

connessione = $ connessione;  public function loadUserByUsername ($ username) return $ this-> getUser ($ username);  funzione privata getUser ($ username) $ sql = "SELECT * FROM sf_users WHERE username =: name"; $ stmt = $ this-> connection-> prepare ($ sql); $ stmt-> bindValue ("nome", $ username); $ Stmt-> execute (); $ row = $ stmt-> fetch (); if (! $ row ['username']) $ exception = new UsernameNotFoundException (sprintf ('Username "% s" non trovato nel database. ", $ row [' username '])); $ Eccezione-> SetUserName ($ username); lanciare $ exception;  else return new User ($ row ['username'], $ row ['password'], $ row ['ruoli']);  public function refreshUser (UserInterface $ user) if (! $ user instanceof User) throw new UnsupportedUserException (sprintf ('Le istanze di "% s" non sono supportate.', get_class ($ user)));  return $ this-> getUser ($ user-> getUsername ());  public function supportsClass ($ class) return 'Sfauth \ User \ User' === $ class; 

Il provider utente deve implementare il UserProviderInterface interfaccia. Stiamo utilizzando il DBAL della dottrina per eseguire le operazioni relative al database. Come abbiamo implementato il UserProviderInterface interfaccia, dobbiamo implementare il loadUserByUsername, refreshUser, e supportsClass metodi.

Il loadUserByUsername il metodo dovrebbe caricare l'utente con il nome utente, e questo è fatto nel getUser metodo. Se l'utente viene trovato, restituiamo il corrispondente Sfauth \ User \ User oggetto, che implementa il Interfaccia utente interfaccia.

D'altra parte, il refreshUser il metodo aggiorna il fornito Utente oggetto recuperando le ultime informazioni dal database.

E infine, il supportsClass metodo controlla se il DatabaseUserProvider il provider supporta la classe utente fornita.

La classe del provider di autenticazione del database

Infine, dobbiamo implementare il provider di autenticazione utente, che definisce la logica di autenticazione: come un utente è autenticato. Nel nostro caso, dobbiamo abbinare le credenziali dell'utente al database MySQL, quindi è necessario definire la logica di autenticazione di conseguenza.

Vai avanti e crea il src / utente / DatabaseAuthenticationProvider.php file con il seguente contenuto.

userProvider = $ userProvider;  funzione protetta retrieveUser ($ username, token UsernamePasswordToken $) $ user = $ token-> getUser (); if ($ user instanceof UserInterface) return $ user;  prova $ user = $ this-> userProvider-> loadUserByUsername ($ username); if (! $ user instanceof UserInterface) throw new AuthenticationServiceException ('Il provider utente deve restituire un oggetto UserInterface.');  return $ user;  catch (UsernameNotFoundException $ e) $ e-> setUsername ($ username); buttare $ e;  catch (\ Exception $ e) $ e = new AuthenticationServiceException ($ e-> getMessage (), 0, $ e); $ E-> setToken ($ token); buttare $ e;  funzione protetta checkAuthentication (UserInterface $ user, UsernamePasswordToken $ token) $ currentUser = $ token-> getUser (); if ($ currentUser instanceof UserInterface) if ($ currentUser-> getPassword ()! == $ user-> getPassword ()) lancia nuova AuthenticationException ('Le credenziali sono state cambiate da un'altra sessione.');  else $ password = $ token-> getCredentials (); if (vuoto ($ password)) lancia nuova AuthenticationException ('Password non può essere vuota.');  if ($ user-> getPassword ()! = md5 ($ password)) lancia nuova AuthenticationException ('Password non valida.'); 

Il DatabaseAuthenticationProvider il provider di autenticazione estende il UserAuthenticationProvider classe astratta. Quindi, abbiamo bisogno di implementare il retrieveUser e checkAuthentication metodi astratti.

Il lavoro del retrieveUser il metodo è caricare l'utente dal fornitore dell'utente corrispondente. Nel nostro caso, userà il DatabaseUserProvider user provider per caricare l'utente dal database MySQL.

D'altra parte, il checkAuthentication metodo esegue i controlli necessari per autenticare l'utente corrente. Tieni presente che ho utilizzato il metodo MD5 per la crittografia della password. Ovviamente, è necessario utilizzare metodi di crittografia più sicuri per archiviare le password degli utenti.

Come funziona Complessivamente

Finora, abbiamo creato tutti gli elementi necessari per l'autenticazione. In questa sezione vedremo come mettere tutto insieme per impostare la funzionalità di autenticazione.

Vai avanti e crea il db_auth.php file e popolarlo con il seguente contenuto.

 'mysql: // USERNAME: PASSWORD @ HOSTNAME / DATABASE_NAME'), nuovo \ Doctrine \ DBAL \ Configuration ()); // avvia il nostro utente personalizzato db user $ userProvider = new DatabaseUserProvider ($ doctrineConnection); // useremo UserChecker predefinito, è usato per controllare controlli aggiuntivi come blocco account / scaduto, ecc. // è possibile implementare il proprio implementando l'interfaccia UserCheckerInterface $ userChecker = new UserChecker (); // avvia il nostro provider di autenticazione db personalizzato $ dbProvider = new DatabaseAuthenticationProvider ($ userProvider, $ userChecker, 'frontend'); // init authentication provider manager $ authenticationManager = new AuthenticationProviderManager (array ($ dbProvider)); prova // init un / pw, di solito otterrai questi dalla variabile $ _POST, inviata dall'utente finale $ username = 'admin'; $ password = 'admin'; // get touthenticated token $ unauthenticatedToken = new UsernamePasswordToken ($ username, $ password, 'frontend'); // autenticazione utente e get token autenticato $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken); // abbiamo il token autenticato (l'utente ha effettuato l'accesso ora), può essere memorizzato in una sessione per uso futuro echo $ authenticatedToken; echo "\ n";  catch (AuthenticationException $ e) echo $ e-> getMessage (); echo "\ n"; 

Richiama il flusso di autenticazione che è stato discusso all'inizio di questo articolo: il codice sopra riportato riflette quella sequenza.

La prima cosa era recuperare le credenziali dell'utente e creare un token non autenticato.

$ unauthenticatedToken = new UsernamePasswordToken ($ username, $ password, 'frontend');

Successivamente, abbiamo passato quel token al gestore di autenticazione per la convalida.

// autenticazione utente e get token autenticato $ authenticatedToken = $ authenticationManager-> authenticate ($ unauthenticatedToken);

Quando viene chiamato il metodo di autenticazione, un sacco di cose stanno accadendo dietro le quinte.

In primo luogo, il gestore autenticazione seleziona un provider di autenticazione appropriato. Nel nostro caso, è il DatabaseAuthenticationProvider provider di autenticazione, che verrà selezionato per l'autenticazione.

Successivamente, recupera l'utente con il nome utente dal DatabaseUserProvider fornitore di utenti. Finalmente, il checkAuthentication metodo esegue i controlli necessari per autenticare la richiesta dell'utente corrente.

Se desideri testare il db_auth.php script, dovrai creare il sf_users tabella nel tuo database MySQL.

CREATE TABLE 'sf_users' ('id' int (11) NOT NULL AUTO_INCREMENT, 'username' varchar (255) NOT NULL, 'password' varchar (255) NOT NULL, 'ruoli' enum ('registrato', 'moderatore', 'admin') DEFAULT NULL, PRIMARY KEY ('id')) ENGINE = InnoDB; INSERISCI I VALORI "sf_users" (1, "admin", "21232f297a57a5a743894a0e4a801fc3", "admin");

Vai avanti e avvia il db_auth.php script per vedere come va. Al completamento con esito positivo, dovresti ricevere un token autenticato, come mostrato nel seguente snippet.

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

Una volta che l'utente è autenticato, è possibile memorizzare il token autenticato nella sessione per le richieste successive.

E con questo, abbiamo completato la nostra semplice demo di autenticazione!

Conclusione

Oggi, abbiamo esaminato il componente Symfony Security, che consente di integrare funzionalità di sicurezza nelle applicazioni PHP. Nello specifico, abbiamo discusso la funzione di autenticazione fornita dal sottocomponente symfony / security-core e ti ho mostrato un esempio di come questa funzionalità può essere implementata nella tua app.

Sentiti libero di postare i tuoi pensieri usando il feed qui sotto!