Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 32

Configuration CORS pour React

Recommended resources

Bonjour ! Dans la leçon précédente, nous avons créé une documentation d'API interactive et professionnelle avec OpenAPI et Swagger. Nous disposons maintenant d'un backend robuste et bien documenté. L'étape suivante est de le rendre accessible à notre application frontend React.

Cependant, si vous essayez de faire une requête depuis une application React (tournant, par exemple, sur localhost:3000) vers votre API Spring Boot (sur localhost:8080), vous ferez face à un mur. Le navigateur bloquera la requête pour des raisons de sécurité.

L'objectif de cette leçon est de franchir ce mur en apprenant à configurer la politique CORS (Cross-Origin Resource Sharing) pour autoriser les requêtes depuis un frontend React. C'est la dernière étape pour finaliser notre API professionnelle avant de nous plonger dans des aspects de sécurité plus avancés.

1. Le Problème : La Politique de Même Origine (Same-Origin Policy)

Les navigateurs web implémentent une politique de sécurité fondamentale appelée Same-Origin Policy. Cette politique empêche une page web ou un script de faire des requêtes vers une ressource qui n'a pas la même "origine" (combinaison de protocole, domaine et port) que la page elle-même.

  • Frontend React : http://localhost:3000 -> Origine 1
  • Backend Spring Boot : http://localhost:8080 -> Origine 2

Puisque les ports sont différents, les origines sont différentes. Le navigateur bloquera donc la requête.

Connecting React and Spring: Understanding CORS Issues
Cette image illustre parfaitement notre situation : une application React essaie de contacter une API Spring Boot sur un port différent, ce qui déclenche une erreur CORS dans le navigateur.

Le Cross-Origin Resource Sharing (CORS) est un mécanisme qui permet d'assouplir cette politique de manière contrôlée. Il utilise des en-têtes HTTP supplémentaires pour indiquer à un navigateur que le serveur autorise une application web d'une origine donnée à accéder à ses ressources.

Pour une explication détaillée des concepts, vous pouvez consulter la documentation de référence du MDN.

Cross-origin resource sharing (CORS) - HTTP | MDN

Lisez l'introduction et la section "Aperçu fonctionnel" de l'article MDN sur le CORS. Cela vous donnera une base solide sur le "pourquoi" de CORS et le rôle des requêtes préliminaires (preflight).

Concentrez-vous sur la définition du CORS, la raison de son existence (sécurité), et la mention des requêtes préliminaires avec la méthode OPTIONS.


2. Voir l'Erreur en Pratique et les Solutions Simples

La meilleure façon de comprendre CORS est de voir l'erreur se produire, puis de la corriger. La vidéo suivante simule exactement ce scénario. Bien que l'exemple utilise Vue.js, le principe et l'erreur sont identiques pour une application React.

Spring Security CORS: How to configure CORS in Spring Boot & Spring Security

Regardez la première partie de cette excellente vidéo par Dan Vega. Elle vous montrera comment mettre en place un projet simple qui déclenche inévitablement une erreur CORS, puis comment la résoudre avec la méthode la plus simple : l'annotation @CrossOrigin.

Regardez la vidéo de 00:00 à 13:00. Observez attentivement : La création d'une API simple et d'un frontend qui l'appelle (jusqu'à 07:24). L'apparition de l'erreur CORS dans la console du navigateur (07:24 - 09:15). La résolution de l'erreur en utilisant @CrossOrigin sur le contrôleur, puis de manière plus fine sur une méthode spécifique (09:15 - 13:00).

Comme vous l'avez vu, il existe plusieurs façons de configurer CORS dans Spring Boot sans Spring Security.

Méthode 1 : L'annotation @CrossOrigin

C'est la solution la plus rapide. Vous pouvez l'appliquer à une classe de contrôleur entière ou à des méthodes spécifiques.

@RestController
@RequestMapping("/api/products")
// Applique la politique CORS à tous les endpoints de ce contrôleur
@CrossOrigin(origins = "http://localhost:3000")
public class ProductController {

    @GetMapping
    public ResponseEntity<List<Product>> getAllProducts() {
        // ...
    }

    @PostMapping
    // Applique (ou surcharge) la politique pour cet endpoint uniquement
    // @CrossOrigin(origins = "http://localhost:4200")
    public ResponseEntity<Product> createProduct(@RequestBody Product product) {
        // ...
    }
}
Spring Boot @CrossOrigin Annotation Example
Comme le montre cette image, l'annotation `@CrossOrigin` peut être utilisée pour spécifier précisément quelle(s) origine(s) sont autorisées.

Bien que simple, cette approche dissémine la configuration CORS dans toute l'application, ce qui peut devenir difficile à maintenir.

Méthode 2 : Configuration Globale via WebMvcConfigurer

Une approche plus propre consiste à centraliser la configuration. On peut créer une classe de configuration qui implémente WebMvcConfigurer et surcharge la méthode addCorsMappings.

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**") // Applique CORS à tous les chemins sous /api/
            .allowedOrigins("http://localhost:3000")
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .allowedHeaders("*")
            .allowCredentials(true);
    }
}

Cette méthode est bien meilleure car elle centralise la logique. La vidéo de Dan Vega que vous avez regardée (section de 13:00 à 15:27) montre également comment mettre cela en œuvre.

Cependant, il y a un piège majeur : cette configuration peut ne pas fonctionner dès que vous ajoutez Spring Security.


3. La Méthode Professionnelle : Intégrer CORS avec Spring Security

Dans une application professionnelle, vous utiliserez presque toujours Spring Security. La chaîne de filtres de Spring Security intercepte les requêtes avant que le mécanisme WebMvcConfigurer n'ait la chance de les traiter. Par conséquent, si la requête CORS (en particulier la requête OPTIONS de preflight) n'est pas autorisée par Spring Security, elle sera rejetée avec une erreur 401 Unauthorized ou 403 Forbidden, et vous verrez toujours une erreur CORS dans le navigateur.

La solution correcte est de déclarer la configuration CORS directement au sein de la configuration de Spring Security.

Spring Security CORS: How to configure CORS in Spring Boot & Spring Security

Cette partie de la vidéo de Dan Vega est la plus importante de la leçon. Elle explique pourquoi la configuration précédente échoue avec Spring Security et montre la bonne façon de faire les choses.

Regardez la vidéo de 15:27 à 22:38. Portez une attention particulière aux points suivants : L'erreur qui réapparaît après l'ajout de Spring Security (17:37). L'explication du conflit entre CORS et Spring Security. L'ajout de .cors(Customizer.withDefaults()) à la SecurityFilterChain. La création d'un bean @Bean de type CorsConfigurationSource qui contient la configuration CORS réelle. C'est là que la magie opère.

Voici à quoi ressemble la configuration finale et correcte dans votre classe SecurityConfig :

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    // ... votre bean UserDetailsService et PasswordEncoder

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            // C'EST LA LIGNE IMPORTANTE : on dit à Spring Security d'appliquer la config CORS
            .cors(Customizer.withDefaults()) 
            .authorizeHttpRequests(req -> req
                .requestMatchers("/api/auth/**").permitAll() // Endpoints d'authentification publics
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    // C'EST LE BEAN QUI CONTIENT LA CONFIGURATION
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // Spécifiez l'origine de votre frontend React
        configuration.setAllowedOrigins(List.of("http://localhost:3000", "http://localhost:5173")); 
        configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
        configuration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
        configuration.setAllowCredentials(true); // Important si vous gérez des cookies/sessions

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration); // Applique cette config à toutes les routes
        return source;
    }
}

Cette approche garantit que la politique CORS est évaluée au bon moment dans la chaîne de traitement des requêtes, en parfaite harmonie avec vos autres règles de sécurité.


Conclusion

Vous avez maintenant ajouté une compétence essentielle à votre arsenal de développeur backend. Savoir configurer correctement CORS est indispensable pour construire des applications full-stack modernes.

Points clés à retenir :

  • CORS est une politique du navigateur, pas une erreur du serveur. Le serveur doit simplement envoyer les bons en-têtes de réponse pour satisfaire le navigateur.
  • Il existe des solutions rapides comme @CrossOrigin, mais elles sont moins maintenables.
  • La centralisation via WebMvcConfigurer est meilleure, mais elle entre en conflit avec Spring Security.
  • La solution de niveau professionnel consiste à intégrer la configuration CORS directement dans la SecurityFilterChain en fournissant un bean CorsConfigurationSource.
  • Assurez-vous de n'autoriser que les origines nécessaires (votre frontend) en production et d'être précis sur les méthodes et en-têtes autorisés.

Notre API est maintenant entièrement prête à être consommée par un client externe. Nous avons couvert sa conception, sa documentation et maintenant sa politique d'accès cross-origin.

Dans le prochain module, nous allons faire une plongée en profondeur dans l'outil que nous venons d'utiliser : Spring Security. Notre première leçon portera sur l'intégration de Spring Security et la compréhension de son architecture basée sur une chaîne de filtres, un concept que nous venons d'effleurer aujourd'hui.