Je développe une application Spring Boot avec une interface Reste et une Dart en façade.
XMLHttpRequest exécute une requête OPTIONS totalement gérée. 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. Origin ' http: // localhost: 63343 ' n'est donc pas autorisé à accéder.
Après quelques opérations de débogage, j’ai trouvé ce qui suit: Dans RepositoryRestHandlerMapping, aucune configuration cors n'est présente/définie au moment de la création et ne sera donc pas reconnue en tant que ressource/chemin 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 définir le Cors par annotation:
@CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false")
public interface ProductRepository extends CrudRepository<Product, String> {
}
En-têtes de demande brute:
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 brutes:
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
Qu'est-ce qui me manque?
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 compatibles CORS.
Mais maintenant que DATAREST-573 a été corrigé, RepositoryRestConfiguration
expose maintenant une getCorsRegistry()
pour la configuration globale et les annotations @CrossOrigin
sur les référentiels sont également reconnues; il s'agit donc de l'approche recommandée. Voir https://stackoverflow.com/a/42403956/1092077 answer pour des exemples concrets.
Pour les personnes qui doivent s'en tenir à Spring Data REST 2.5 (Hopper) ou à des versions antérieures, la meilleure solution consiste à utiliser une approche basée sur le filtre. Vous pouvez évidemment utiliser Tomcat, Jetty ou celui-ci , mais sachez que Spring Framework 4.2 fournit également un CorsFilter
qui utilise la même logique de traitement CORS que celle de @CrossOrigin
et de addCorsMappings(CorsRegistry registry)
. En passant une UrlBasedCorsConfigurationSource
instance au paramètre du constructeur CorsFilter
, vous pouvez facilement obtenir quelque chose d'aussi puissant que la prise en charge globale de CORS native de Spring.
Si vous utilisez Spring Boot (qui prend en charge les beans Filter
), cela peut ressembler à 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 façons de traiter:
L'annotation @CrossOrigin
avec la spécification de origins
, methods
et allowedHeaders
sur une interface @RepositoryRestResource
.
@CrossOrigin(...)
@RepositoryRestResource
public interface PageRepository extends CrudRepository<Page, Long> { ... }
Une configuration globale avec la RepositoryRestConfiguration
dans une classe @Configuration
. Le marquage des référentiels avec le @CrossOrigin
n’est alors pas nécessaire.
@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 suggérée dans la réponse acceptée ci-dessus ne fonctionnait pas pour moi après la mise à niveau de Spring Boot 1.5.2 à 1.5.6.
Comme l'a également souligné le commentaire de @ BigDong, l'exception que j'ai eue était:
BeanInstantiationException: Echec de l'instanciation [javax.servlet.Filter]: La méthode d'usine 'springSecurityFilterChain' a lancé une exception; exception imbriquée est org.springframework.beans.factory.BeanNotOfRequiredTypeException: Un bean nommé 'corsFilter' devrait être de type 'org.springframework.web.filter.CorsFilter' mais était en fait de type 'org.springframework.boot.web.web. .servlet.FilterRegistrationBean
Voici donc ce que j'ai proposé 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 ne pouvais pas attacher une CorsFilter
au pipeline de demandes au bon moment. J'ai donc 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 quelques références supplémentaires sur le sujet qui m'ont aidé à trouver cette réponse:
J'essayais de frapper le service Spring Spring d'angular . Le projet Spring Spring est déployé sur le serveur Tomcat et angular est le serveur angulaire par défaut . suivre
https://juristr.com/blog/2016/11/configure-proxy-api-angular-cli/
mais le problème persiste toujours ... Grâce à mon ancien 'Abbas bhai', il a suggéré d'ajouter une configuration dans le fichier de configuration du ressort pour éviter ce problème, j'ai donc ajouté ce code dans la configuration du printemps.
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan("org.liferayasif.backend")
public class RestConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter#addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry)
* To avoid 'Access-Control-Allow-Origin'
* Above error arising when I am hitting from angular to our rest service
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
Cette méthode a résolu mes cors "Access-Control-Allow-Origin".
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
Pour référence peut télécharger mon projet entier
Mon lien URL github:
https://github.com/asifaftab87/SpringPersistenceHibernate
Direction générale - sécurité
Projet - Modèle