CORS con Spring

1. Panoramica

In qualsiasi browser moderno, Cross-Origin Resource Sharing (CORS) è una specifica rilevante con l'emergere di client HTML5 e JS che consumano dati tramite API REST.

In molti casi, l'host che serve il JS (ad es. Example.com ) è diverso dall'host che serve i dati (ad es. Api.example.com ). In tal caso, CORS abilita la comunicazione tra domini.

Spring fornisce supporto di prima classe per CORS, offrendo un modo semplice e potente per configurarlo in qualsiasi applicazione Web Spring o Spring Boot.

2. Configurazione CORS metodo controller

L'abilitazione di CORS è semplice: basta aggiungere l'annotazione @CrossOrigin .

Possiamo implementarlo in molti modi diversi.

2.1. @CrossOrigin su un metodo del gestore annotato @ RequestMapping

@RestController @RequestMapping("/account") public class AccountController { @CrossOrigin @RequestMapping(method = RequestMethod.GET, path = "/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }

Nell'esempio sopra, abbiamo abilitato CORS solo per il metodo retrieve () . Possiamo vedere che non abbiamo impostato alcuna configurazione per l' annotazione @CrossOrigin , quindi utilizza i valori predefiniti:

  • Sono consentite tutte le origini
  • I metodi HTTP consentiti sono quelli specificati nell'annotazione @RequestMapping (per questo esempio è GET)
  • Il tempo di memorizzazione nella cache della risposta di verifica preliminare ( maxAge) è di 30 minuti

2.2. @CrossOrigin sul controller

@CrossOrigin(origins = "//example.com", maxAge = 3600) @RestController @RequestMapping("/account") public class AccountController { @RequestMapping(method = RequestMethod.GET, path = "/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }

Questa volta, abbiamo aggiunto @CrossOrigin a livello di classe. Di conseguenza, entrambi i metodi retrieve () e remove () lo hanno abilitato. Possiamo personalizzare la configurazione specificando il valore di uno degli attributi di annotazione: origins , methods , allowedHeaders , ExposedHeaders , allowCredentials o maxAge.

2.3. @CrossOrigin su controller e metodo gestore

@CrossOrigin(maxAge = 3600) @RestController @RequestMapping("/account") public class AccountController { @CrossOrigin("//example.com") @RequestMapping(method = RequestMethod.GET, "/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } }

Spring combinerà gli attributi di entrambe le annotazioni per creare una configurazione CORS unita.

In questo esempio, entrambi i metodi avranno una maxAge di 3600 secondi, il metodo remove () consentirà tutte le origini, ma il metodo retrieve () consentirà solo le origini da //example.com.

3. Configurazione CORS globale

In alternativa alla configurazione basata su annotazioni a grana fine, Spring ci consente di definire alcune configurazioni CORS globali dai controller. È simile all'utilizzo di una soluzione basata su filtro , ma può essere dichiarato all'interno di Spring MVC e combinato con una configurazione @CrossOrigin a grana fine .

Per impostazione predefinita, sono consentiti tutti i metodi Origins e GET, HEAD e POST.

3.1. JavaConfig

@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**"); } }

L'esempio precedente abilita le richieste CORS da qualsiasi origine a qualsiasi endpoint nell'applicazione.

Se vogliamo bloccarlo un po 'di più, il metodo registry.addMapping restituisce un oggetto CorsRegistration , che possiamo usare per una configurazione aggiuntiva. C'è anche un metodo allowedOrigins che ci consente di specificare un array di origini consentite. Questo può essere utile se dobbiamo caricare questo array da una fonte esterna in fase di runtime.

Inoltre, ci sono anche allowedMethods , allowedHeaders , ExposedHeaders , maxAge e allowCredentials che possiamo utilizzare per impostare le intestazioni di risposta e le opzioni di personalizzazione.

3.2. Spazio dei nomi XML

Questa configurazione XML minima abilita CORS su un pattern di percorso / ** con le stesse proprietà predefinite di JavaConfig:

È anche possibile dichiarare diversi mapping CORS con proprietà personalizzate:

4. CORS con Spring Security

Se usiamo Spring Security nel nostro progetto, dobbiamo fare un passo in più per assicurarci che funzioni bene con CORS. È perché CORS deve essere elaborato prima. In caso contrario, Spring Security rifiuterà la richiesta prima che raggiunga Spring MVC.

Fortunatamente, Spring Security fornisce una soluzione pronta all'uso:

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and()... } }

Questo articolo lo spiega in modo più dettagliato.

5. Come funziona

Le richieste CORS vengono inviate automaticamente ai vari HandlerMappings registrati . Gestiscono le richieste di verifica preliminare CORS e intercettano richieste CORS semplici ed effettive utilizzando un'implementazione CorsProcessor ( DefaultCorsProcessor per impostazione predefinita) per aggiungere le intestazioni di risposta CORS pertinenti (come Access-Control-Allow-Origin ).

CorsConfiguration ci consente di specificare come devono essere elaborate le richieste CORS: origini, intestazioni e metodi consentiti, tra gli altri. Possiamo fornirlo in vari modi:

  • AbstractHandlerMapping # setCorsConfiguration () consente di specificare una mappa con diversi CorsConfiguration mappati su schemi di percorso come / api / **
  • Le sottoclassi possono fornire la propria CorsConfiguration sovrascrivendo il metodo AbstractHandlerMapping # getCorsConfiguration (Object, HttpServletRequest)
  • I gestori possono implementare l' interfaccia CorsConfigurationSource (come ora fa ResourceHttpRequestHandler ) per fornire una CorsConfiguration per ogni richiesta

6. Conclusione

In questo articolo, abbiamo mostrato come Spring fornisce supporto per abilitare CORS nella nostra applicazione.

Abbiamo iniziato con la configurazione del controller. Abbiamo visto che dobbiamo solo aggiungere l'annotazione @CrossOrigin per abilitare CORS a un particolare metodo o all'intero controller.

Infine, abbiamo anche visto che se vogliamo controllare la configurazione CORS al di fuori dei controller, possiamo eseguirlo senza problemi nei file di configurazione, utilizzando JavaConfig o XML.

Il codice sorgente completo per gli esempi è disponibile su GitHub.