Données de repos et cors

Je développe une application Spring Boot avec une interface Rest et une fléchette.

XMLHttpRequest exécute une requête OPTIONS qui est gérée de manière totalement correcte. Après cela, la demande finale GET (“/ products”) est émise et échoue:

Aucun en-tête “Access-Control-Allow-Origin” n’est présent sur la ressource demandée. L’origine ‘ http: // localhost: 63343 ‘ n’est donc pas autorisée.

Après un débogage, j’ai trouvé ce qui suit: La classe AbstractHandlerMapping.corsConfiguration est remplie pour toutes les sous-classes, à l’exception de RepositoryRestHandlerMapping. Dans RepositoryRestHandlerMapping, aucune corsConfiguration n’est présente / définie au moment de la création et ne sera donc pas reconnue comme chemin / ressource cors.
=> Aucun en-tête CORS attaché
Est-ce que cela pourrait être le problème? Comment puis-je le définir?

Classes de configuration:

@Configuration public class RestConfiguration extends RepositoryRestMvcConfiguration { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowCredentials(false).allowedOrigins("*").allowedMethods("PUT", "POST", "GET", "OPTIONS", "DELETE").exposedHeaders("Authorization", "Content-Type"); } ... } 

J’ai même essayé de régler le cors par annotation:

 @CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false") public interface ProductRepository extends CrudRepository { } 

En-têtes de demande bruts:

 GET /products HTTP/1.1 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 authorization: Basic dXNlcjpwYXNzd29yZA== User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/43.0.2357.130 Chrome/43.0.2357.130 Safari/537.36 Content-Type: application/json Accept: */* Referer: http://localhost:63343/inventory-web/web/index.html Accept-Encoding: gzip, deflate, sdch Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4 

En-têtes de réponse bruts:

 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: application/hal+json;charset=UTF-8 Transfer-Encoding: chunked Date: Thu, 30 Jul 2015 15:58:03 GMT 

Versions utilisées: Spring Boot 1.3.0.M2 Spring 4.2.0.RC2

Que me manque-t-il?

En effet, avant Spring Data REST 2.6 (Ingalls), seules les instances HandlerMapping créées par Spring MVC WebMvcConfigurationSupport et les contrôleurs annotés avec @CrossOrigin étaient conscientes de @CrossOrigin .

Mais maintenant que DATAREST-573 a été corrigé, RepositoryRestConfiguration expose désormais un getCorsRegistry() pour la configuration globale et les annotations @CrossOrigin sur les référentiels sont également reconnues. C’est l’approche recommandée. Voir https://stackoverflow.com/a/42403956/1092077 réponse pour des exemples concrets.

Pour les personnes qui doivent respecter Spring Data REST 2.5 (Hopper) ou les versions précédentes, je pense que la meilleure solution consiste à utiliser une approche basée sur les filtres. Vous pouvez évidemment utiliser Tomcat, Jetty ou celui-ci , mais sachez que Spring Framework 4.2 fournit également un CorsFilter utilisant la même logique de traitement @CrossOrigin que @CrossOrigin et addCorsMappings(CorsRegistry registry) . En transmettant une instance CorsFilter paramètre du constructeur CorsFilter , vous pourriez facilement obtenir quelque chose d’aussi puissant que le support global CORS natif de Spring.

Si vous utilisez Spring Boot (qui prend en charge les beans Filter ), cela pourrait être quelque chose comme:

 @Configuration public class RestConfiguration { @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } } 

Depuis que le train Ingalls a été réalisé , le support de CORS dans Spring Data est maintenant disponible. Il y a deux manières de traiter:

  1. L’annotation @CrossOrigin avec des origins , des methods et des allowedHeaders via une interface @RepositoryRestResource .

     @CrossOrigin(...) @RepositoryRestResource public interface PageRepository extends CrudRepository { ... } 
  2. Une configuration globale avec RepositoryRestConfiguration dans une classe @Configuration . Marquage des référentiels par le @CrossOrigin n’est pas nécessaire alors.

     @Configuration public class GlobalRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter { @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.getCorsRegistry() .addMapping(CORS_BASE_PATTERN) .allowedOrigins(ALLOWED_ORIGINS) .allowedHeaders(ALLOWED_HEADERS) .allowedMethods(ALLOWED_METHODS); } } 

Pour une raison quelconque, l’approche proposée dans la réponse acceptée ci-dessus n’a pas fonctionné pour moi après la mise à niveau de Spring Boot 1.5.2 vers 1.5.6.

Comme l’a également souligné le commentaire de @ BigDong, l’exception que j’ai eue était:

BeanInstantiationException: Impossible d’instancier [javax.servlet.Filter]: La méthode d’usine ‘springSecurityFilterChain’ a généré une exception; l’exception nestede est org.springframework.beans.factory.BeanNotOfRequiredTypeExcep‌ tion: le bean nommé ‘corsFilter’ devrait être de type ‘org.springframework.web.filter.CorsFilter’ mais était en réalité de type ‘org.springframework.boot.web .servlet.FilterRegistrationBean

Donc, voici ce que j’ai trouvé pour obtenir une configuration CORS “globale” pour tous les points de terminaison de notre API REST, qu’ils soient implémentés avec Spring Data Rest ou Spring MVC, avec tous les points de terminaison protégés par Spring Security.

Je n’ai pas réussi à CorsFilter un CorsFilter dans le pipeline de requêtes au bon endroit, alors j’ai plutôt configuré SDR et MVC séparément, mais en utilisant la même configuration pour leur CorsRegistry via cet assistant:

 public static void applyFullCorsAllowedPolicy(CorsRegistry registry) { registry.addMapping("/**") // .allowedOrigins("*") // .allowedMethods("OPTIONS", "HEAD", "GET", "PUT", "POST", "DELETE", "PATCH") // .allowedHeaders("*") // .exposedHeaders("WWW-Authenticate") // .allowCredentials(true) .maxAge(TimeUnit.DAYS.toSeconds(1)); } 

Et puis pour MVC:

 @Configuration @EnableWebSecurity(debug = true) @EnableGlobalMethodSecurity(prePostEnabled = true) public class CustomWebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // enables CORS as per // https://docs.spring.io/spring-security/site/docs/current/reference/html/cors.html#cors http.cors() .and() // ... } @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { applyFullCorsAllowedPolicy(registry); } }; } } 

Et puis pour SDR:

 public class CustomRepositoryRestMvcConfiguration extends RepositoryRestConfigurerAdapter { @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.setReturnBodyOnCreate(true); config.setReturnBodyForPutAndPost(true); config.setReturnBodyOnUpdate(true); config.setMaxPageSize(250); config.setDefaultPageSize(50); config.setDefaultMediaType(MediaTypes.HAL_JSON); config.useHalAsDefaultJsonMediaType(true); CustomWebSecurityConfiguration.applyFullCorsAllowedPolicy(config.getCorsRegistry()); } 

Voici une autre référence sur le sujet qui m’a aidé à trouver cette réponse: