web-dev-qa-db-fra.com

Filtre Spring Boot CORS - Le canal de contrôle en amont CORS n'a pas réussi

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:

 enter image description here

Qu'est-ce que je fais mal et comment configurer correctement les en-têtes CORS afin d'éviter ce problème? 

19
alexanoid

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;
    }

}
39
alexanoid

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);
}
6
Romell

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.

2
Vijay Kalidindi

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.

0
Bamtak

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;
    }
0
Niranjan Panigrahi