Nell’articolo Autenticazione delle Chiamate API abbiamo descritto alcuni metodi che possono essere applicati per la protezione delle chiamate API, ed in particolare abbiamo visto come la Basic Authentication è, tra tutti, il metodo più semplice. In questo articolo vediamo come sia possibile applicarlo per proteggere chiamate REST API implementate con il framework Spring Boot.
Dependency
Nel mondo Spring la sicurezza delle chiamate web è implementata nel progetto Spring Security. Il modo più semplice per utilizzarlo in un progetto Spring Boot è quello di includere la dipendenza spring-boot-starter-security.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" <modelVersion>4.0.0</modelVersion> .... <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> </project> |
Configurazione
Per abilitare il supporto all’autenticazione e l’autorizzazione delle API implementate in Spring Boot, è possibile procedere configurando la classe di utilità WebSecurityConfigurerAdapter
. Essa configura l’applicazione in modo che richieda, ad un qualsiasi client, di essere autenticato prima di poter accedere ad una URL o a tutte le URL gestite all’interno della nostra applicazione.
La configurazione della security avviene, quindi, attraverso l’overriding dei diversi metodo configure()
di cui la classe si compone. Per il nostro esempio i metodi da sovrascrivere sono:
configure(HttpSecurity http)
: consente di manipolare la classeHttpSecurity
utilizzata per configurare la sicurezza delle richieste HTTP. Con riferimento alla configurazione di Spring Security mediante file XML, tale classe è la duale del tag<http>
(si veda Primi Passi con Spring Security (parte 3)).configure(AuthenticationManagerBuilder auth)
: consente di configurare la classeAuthenticationManagerBuilder
che è utilizzata dal framework per ottenere una implementazione dell’AuthenticationManager
il quale è usato per autenticare l’utente.
Concludendo la classe SecurityConfig
utilizzata per implementare la Basic Authentication avrà il seguente aspetto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests().anyRequest().authenticated() .and() .httpBasic(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("admin") .password("{noop}password") .roles("USER"); } } |
Si noti che è il metodo httpBasic()
che abilita la Basic Authentication applicata a tutte le URL esposte dall’applicazione.
Il Controller
Per fare un test esponiamo un semplice servizio Rest che all’URL /hello-world restituisce la stringa “Hello World!” nel body della response:
1 2 3 4 5 6 7 8 |
@Controller public class HelloWorldController { @RequestMapping( path="/hello-world", method=RequestMethod.GET ) @ResponseBody public String hello() { return "Hello World!"; } } |
Il Protocollo
Una volta avviata l’applicazione nel momento in cui un client esegue una GET HTTP alla URL http://localhost:8080/hello-world, il server invia al client una richiesta di autenticazione. Tale richiesta è espressa restituendo al client una response con codice HTTP 401 ed inserendo l’header HTTP WWW-Authenticate
, dove sono indicati uno o più schemi di autenticazione ed i relativi parametri (i cosiddetti challenge ). Nel caso di Basic Authentication tale header è così popolato:
WWW-Authenticate: Basic realm="[NOME DEL REALM]"
E’ questo il motivo per cui alcuni browser aprono un pop-up presentando all’utente una maschera di login, come quella mostrata nella figura seguente per chrome:
Infine quando il client vuole inviare le credenziali per l’accesso alla risorsa non deve fare altro che inserire nella richiesta l’header HTTP Authorization
. Tale header è popolato nel seguente modo:
- Username e password sono uniti nella stringa “username:password”
- Il risultato è codificato con base64
- Il metodo di autorizzazione (basic) e uno spazio sono inseriti all’inizio della stringa codificata.
Nel nostro esempio avendo configurato un in memory authentication provider con le credenziali “admin” come login e “password” come password, l’header avrà il seguente aspetto:
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Se si prova a decodificare la string YWRtaW46cGFzc3dvcmQ=
ad esempio inserendola nel tool online https://www.base64decode.org/ si ottiene infatti la string “admin:password” (virgolette escluse).
Concludiamo dicendo che in caso di Basic Authentication le credenziali vengono inviate ad ogni richiesta e che l’operazione di encoding in Base 64 è reversibile. Tutto ciò rende il protocollo non sicuro e deve quindi essere utilizzato in coppia con il protocollo SSL/TLS al fine di cifrare l’intera comunicazione tra client e server.
Codie Sorgente
Il codice sorgente del progetto è disponibile qui basic-auth.