Abbiamo visto finora tutti gli strumenti che Symfony ci mette a disposizione per realizzare un'applicazione Web. Non ci siamo occupati però di come fornire determinati contenuti solo a specifici utenti e ruoli.
Vedremo in questa lezione come Symfony gestisce la sicurezza e come fornire accesso ad alcune pagina attraverso username e password.
Configurazione della Demo
Innanzitutto bisogna specificare che la maggior parte delle impostazioni sono salvate all'interno del file app/config/security.yml
. All'interno della nostra applicazione dovremmo avere qualcosa di questo genere:
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
demo_login:
pattern: ^/demo/secured/login$
security: false
demo_secured_area:
pattern: ^/demo/secured/
form_login:
check_path: _demo_security_check
login_path: _demo_login
logout:
path: _demo_logout
target: _demo
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
Diamo uno sguardo alla sezione firewall. Notiamo che ci sono, tra le altre, due configurazioni:
- "demo_login";
- "demo_secured_area".
demo_secured_area
definisce un'area protetta all'interno del sito in corrispondenza del path /demo/secured
. Se apriamo la nostra applicazione alla url /app_dev.php/demo/secured/hello/World
veniamo infatti rediretti alla pagina di login.
All'interno di questa configurazione ci sono anche delle rotte che definiscono la pagina di login, di logout e di check dei dati immessi dalla form per l'autenticazione. Queste rotte, se non presenti nei file routing.yml
, si trovano come annotation del controller Acme/DemoBundle/Controller/SecuredController.php
. Ad esempio:
/**
* @Route("/demo/secured")
*/
class SecuredController extends Controller
{
/**
* @Route("/login", name="_demo_login")
* @Template()
*/
public function loginAction(Request $request)
L'altra impostazione, demo_login
, che è stata creata prima di quella appena descritta, è un'eccezione che consente, attraverso la proprietà security: false
, di accedere alla pagina di login contenuta all'interno della /demo/secured/
area. Senza questa regola, non sarebbe stato possibile accedere alla pagina di login da utente non loggato.
Nell'esempio notiamo che ci sono due ruoli con cui è possibile effettuare il login: "user" e "admin". Se osserviamo con attenzione il file security.yml
notiamo che tali utenti sono stati generati all'interno del sistema con una username e una password fisse. Queste informazioni sono contenute all'interno della sezione providers
.
La versatilità di Symfony fornisce, infatti, un layer di astrazione che permette di gestire l'autenticazione indipendentemente dall'origine delle informazioni. Un altro provider valido, infatti, potrebbe essere il database come avviene per la quasi totalità delle applicazioni Web.
Un'altra sezione importante è role_hierarchy
in cui andiamo a definire i ruoli gestiti dagli utenti e quelli che ognuno di essi eredita. Notiamo infatti che ROLE_ADMIN
eredita il ruolo ROLE_USER
.
Un esempio di procedura per l'autenticazione
Vediamo ora come realizzare un sistema di autenticazione tutto nostro. Per prima cosa creiamo un controller dedicato. Per comodità definiremo le rotte direttamente all'interno del controller: Acme/DemoBundle/Controller/AdminController.php
.
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class AdminController extends Controller
{
/**
* @Route("/admin")
*/
public function adminAction()
{
return new Response('Pagina admin!');
}
}
Definiamo il nostro controller all'interno del routing Acme/DemoBundle/Resources/config/routing.yml
_admin:
resource: "@AcmeDemoBundle/Controller/AdminController.php"
type: annotation
Andiamo ora a configurare il file security.yml
riscrivendo solo due delle sezioni:
firewalls:
default:
anonymous: ~
http_basic: ~
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Abbiamo abilitato per il path /admin
il login classico simile a quello di Apache che ci chiede username e password. Nell'access_control
abbiamo anche deciso di consentire l'accesso solo ad un utente con ruolo ROLE_ADMIN
. Se apriamo il nostro browser e utilizziamo le credenziali fornite nel file di configurazione (admin/adminpass
) visualizzeremo il messaggio definito nell'adminAction
.
Con pochissime righe di codice abbiamo quindi creato il nostro primo sistema di autenticazione con Symfony. Ovviamente un'applicazione Web reale non può affidarsi ad un sistema di autenticazione così basilare, ma ha bisogno di qualcosa di un po' più avanzato che preveda innanzitutto uno storage esterno da cui accedere per i dati degli utenti.
Si possono scegliere due strade: implementare da soli il sistema di autenticazione utilizzando come provider la base di dati oppure utilizzare uno dei bundle di Symfony.
Nel primo caso esiste una guida molto dettagliata di Symfony che, una volta comprese le basi dell'autenticazione presenti in questo articolo, con poca fatica ci consente di collegare Symfony ad un database di utenti. La guida è presente a questo link.
Come esercitazione è sicuramente la scelta migliore quella di realizzare il sistema con le nostre mani. Nel caso, invece, ci si voglia affidare a qualcosa di più avanzato e completo, possiamo installare il bundle FriendsOfSymfony/FOSUserBundle. È sicuramente uno dei migliori bundle di Symfony per gestire gli utenti in un'applicazione Web. La libreria fornisce già un sistema di autenticazione, registrazione, recupero password, modifica profilo e molte altre funzionalità.