In questo post aggiungeremo il controllo accessi ai metodi esposti nell’esempio visto in precedenza. Le modifiche rispetto al progetto originale sono abbastanza semplici per cui in questo articolo analizzeremo solamente il nuovo codice aggiunto.
Premetto che esistono diversi modi di fornire un’autenticazione sicura ai nostri servizi: potremmo gestire i permessi a livello di servlet container, o lasciare tutto in carico a Jersey che offre il supporto a OAuth protocollo che consente alle applicazioni di accedere alle risorse protette da un servizio Web, come spiega questa guida.
In questo post useremo un’ulteriore soluzione: integreremo Spring Security
per la gestione delle autenticazioni e delle autorizzazioni. Spring Security
è un framework per il controllo accessi potente e altamente personalizzabile, ed è attualmente lo standard per la protezione di applicazioni basate su Spring
.
Le modifiche al web service originale
Passiamo ora al nostro esempio. Come prima cosa creiamo un nuovo progetto Maven
che chiamiamo secureJersey in cui replichiamo tutte le parti sviluppate nel progetto testJersey. Mantenere i due progetti distinti ci aiuta ad analizzare meglio le differenze prima e dopo la modifica.
All’interno del pom.xml
aggiungiamo alcune delle dipendenze del framework Spring
, e le dipendenze del framework Spring Security
come riportato di seguito.
commons-logging commons-logging 1.1.2 org.springframework spring-core 3.2.5.RELEASE org.springframework spring-aop 3.2.5.RELEASE org.springframework spring-context 3.2.5.RELEASE org.springframework.security spring-security-core 3.2.5.RELEASE org.springframework.security spring-security-config 3.2.5.RELEASE org.springframework.security spring-security-web 3.2.5.RELEASE cglib cglib 2.2.2
Il passo successivo è la modifica del file web.xml
.
org.springframework.web.context.ContextLoaderListener org.springframework.web.context.request.RequestContextListener contextConfigLocation /WEB-INF/spring-security.xml springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /*
Analizziamo in breve le modifiche al file:
- L’aggiunta del listener
ContextLoaderListener
ci permette di integrare Spring nella web application. -
RequestContextListener
serve per permettere di richiamare unsessionBean
all’interno di SpringSecurity. - La classe
org.springframework.web.filter.DelegatingFilterProxy
è il filtro di Spring che permette di intercettare le chiamate al nostro servizio. - Il file
spring-security.xml
non è altro che il principale file di configurazione di Spring, ovvero l’ApplicationContext
, definito ad hoc per Spring Security. Vediamo di seguito la sua struttura.
All’interno del tag http
definiamo l’attributo create-session="stateless"
. Questo significa che ad ogni richiesta da parte del client un’istanza del session bean di tipo stateless
viene recuperata dal pool e assegnata al client, quando la richiesta si conclude, l’istanza torna al pool per un successivo riutilizzo.
Inoltre qui vengono definiti i path a cui applicare la sicurezza e i profili a cui in seguito assoceremo login e password.
I tag authentication-manager
e authentication-provider
definiscono le regole con cui un utente viene riconosciuto dal sistema. La lista dei provider che gestiscono il meccanismo di autenticazione è contenuta nel tag authentication-manager
. Ogni tag authentication-provider
ha uno user-service, cioè un meccanismo che definisce qual è il profilo dell’utente e le chiavi di accesso all’interno dell’applicazione.
Con questo abbiamo terminato le modifiche, ora se lanciamo il WebService e richiamiamo uno dei servizi che risiedono sotto il path protetto, il browser ci richiede di inserire le nostre credenziali di accesso.
Chiamare i servizi protetti lato client
Come certamente ricorderete, avevamo definito una web application, che avevamo chiamato , per testare la chiamata ai servizi di testJersey.
Proviamo a chiamare da jsfJersey il nuovo webservice modificando solamente il puntamento alla nuova URL all’interno della classe PersService
:
private static URI getBaseURI() { return UriBuilder.fromUri("secureJersey").build(); }
Lanciando l’applicazione riceveremo un errore di questo tipo:
GET secureJersey/rest/persona returned a response status of 401 Unauthorized
Non siamo autorizzati! Per cui il webservice non trasmette i dati al chiamante se prima non forniamo le credenziali di accesso. A questo punto inseriamo la riga di codice riportata di seguito all’interno del metodo che richiama il servizio protetto:
client.addFilter(new HTTPBasicAuthFilter("user1", "password1"));
La classe HTTPBasicAuthFilter
è fornita da Jersey per il passaggio delle credenziali di autenticazione HTTP basic
. user1
e password1
sono le chiavi di accesso che abbiamo precedentemente definito all’interno del file spring-security.xml
.
Se proviamo a rilanciare l’applicazione ora tutto funziona correttamente.
Conclusioni
In questo post abbiamo reso sicuro il nostro web service con pochi settaggi e senza scrivere una riga di codice Java. Ovviamente questo è un esempio base, Spring Security è un framework avanzato con molte altre funzionalità come l’inserimento di più profili utente con abilitazioni a pattern diversi, la crittografia delle password e molto altro. Per ulteriori approfondimenti vi rimando alla pagina ufficiale.
L’esempio proposto in questo articolo è scaricabile da GitHub.
Pingback: ()