Je dois ajouter un filtre CORS à mon application Web Spring Boot.
J'ai ajouté les mappages CORS comme décrit dans la documentation suivante http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html
C'est ma config:
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
// @formatter:off
registry
.addMapping("/**")
.allowedOrigins(CrossOrigin.DEFAULT_ORIGINS)
.allowedHeaders(CrossOrigin.DEFAULT_ALLOWED_HEADERS)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600L);
// @formatter:on
}
...
}
À l'heure actuelle, lorsque j'essaie d'accéder à mon API, je reçois une erreur suivante:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/api/v1.0/user. (Reason: CORS preflight channel did not succeed).
Ceci est une capture d'écran de la console FF:
Qu'est-ce que je fais mal et comment configurer correctement les en-têtes CORS afin d'éviter ce problème?
J'ai résolu ce problème en créant un nouveau filtre CORS:
@Component
public class CorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token");
response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(request, response);
}
}
}
et l'a ajouté à la configuration de securty:
.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class)
MISE À JOUR - De manière plus moderne que je suis passée à:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
...
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Si le même problème rencontrait le logiciel CORS pour le traitement des données de printemps, c’était le code de filtre que j’avais utilisé.
/**
* Until url{https://jira.spring.io/browse/DATAREST-573} is fixed
*
* @return
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
//config.setAllowCredentials(true); // you USUALLY want this
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Pour ce que ça vaut, la solution de combinaison suivante a fonctionné pour moi:
1.
@Configuration
public class CorsConfiguration {
//This can be used in combination with @CrossOrigin on the controller & method.
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD","OPTIONS")
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept");
}
};
}
}
2. @CrossOrigin
sur la classe RestController. @CrossOrigin
lit les annotations @RequestMapping
et les méthodes HTTP qu'il contient. Les autres demandes sont rejetées avec une erreur CORS.
Mais la solution ci-dessus ne vous servira à rien si vous souhaitez utiliser la sécurité de printemps dans votre projet.
J'utilise la version de démarrage de printemps 1.5.4.RELEASE.
La façon actuellement recommandée de faire la SCRO est
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(true).maxAge(3600);
// Add more mappings...
}
}
Ceci est basé sur https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-cors
Mais vous devez également vous assurer que CORS est activé et que CSRF est désactivé dans votre fichier WebSecurityConfig.
Une fois, j’ai eu un problème où toutes mes méthodes POST ne fonctionnaient pas (renvoi 403 interdit) alors que les méthodes GET fonctionnaient parfaitement, mais ce problème était résolu après la désactivation de CSRF.
Le traitement correct de la demande OPTIONS avant le vol est nécessaire, mais PAS SUFFISANT pour que les demandes de ressources intersite fonctionnent.
Une fois que la demande OPTIONS a été renvoyée avec des en-têtes satisfaisants, toutes les réponses aux demandes ultérieures adressées à la même URL doivent également posséder l'en-tête "Access-Control-Allow-Origin" nécessaire. Dans le cas contraire, le navigateur les avalera et ne pourra même pas afficher dans la fenêtre du débogueur. https://stackoverflow.com/a/11951532/5649869
si vous utilisez Spring-Boot 2, le code ci-dessous suffit pour résoudre le problème cors et le problème de contrôle en amont.
@Override
public void configure(WebSecurity web) throws Exception {
// web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring().antMatchers("/resources/**", "/index.html", "/login.html", "/partials/**", "/template/**", "/",
"/error/**", "/h2-console", "*/h2-console/*");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues();
config.setAllowCredentials(true);// this line is important it sends only specified domain instead of *
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}