Spring, Rest et cross domain

De quoi on parle ?

Le cross domain (croisement de domaine) est un principe qui consiste à faire communiquer deux domaines entre eux. Par exemple, le domaine source-domain.fr souhaite envoyer des données au domaine cible-domain.com et inversement.

Les requêtes HTTP dîtes cross-domain visent donc à récupérer des ressources (scripts, images, feuilles de styles, etc..) localisées sur un serveur d’un domaine différent. Historiquement ces requêtes étaient désactivés pour des raisons évidente de sécurité, et elles étaient donc soumises à la politique de même origine concernant les domaines.

Ce principe prévalait évidement pour les requêtes de type Ajax notamment à travers l’object XmlHttpRequest. La W3C a souhaité faire évoluer ce mécanisme et à mis en place le principe de Cross Origin Resource Sharing (CORS) qui consiste a offrir la possibilité aux serveur de contrôler les accès cross domain.

Le standard de partage de ressources d’origines croisées fonctionne grâce à l’ajout d’entêtes HTTP qui permettent aux serveurs de décrire l’ensemble des origines permises. C’est ensuite le navigateur qui lit cette information et en fait l’usage adéquat. Le navigateur fait d’abord une pré requête afin dé vérifier les options possibles à travers une requête HTTP OPTIONS. Une fois l’approbation du server effectué, la “vraie” requête est effectuée (“POST”,”GET”,etc…).

 

Les différents headers HTTP à ajouter coté serveur sont les suivants:

Access-Control-Allow-Origin

Le serveur indique quels domaines sont autorisés

Access-Control-Allow-Headers

Le serveur indique quels headers sont autorisés

Access-Control-Expose-Headers

Le serveur indique la liste des headers auxquels le navigateur peut accéder

Access-Control-Allow-Methods

Le serveur indique les méthodes HTTP autorisées pour accéder à la ressource.

Nous allons voir comment ajouter ces différents informations dans Spring.

L’environnement technique

Les composants techniques sont les suivants:

  • Java 1.7
  • Spring MVC v4.0.3
  • Spring Boot v1.1.0

 

Rien ne vaut l’exemple

A) Exemple avec un filter (spring < 4.2) :

Puis d’ajouter notre filtre au ServletContext:

 

B) Exemple avec l’annotation @CrossOrigin (spring >= 4.2)

Depuis la version 4.2, Spring à introduit une nouvelle annotation facilitant la gestion du cross origine: @CrossOrigin. Elle peut être placé sur la classe Controller (ajoutant ainsi automatiquement les autorisations sur la route principale), sur les méthodes ou les deux afin de pouvoir surcharger le comportement par défaut.

Par défaut, l’annotation autorise toutes les origines pour la route ainsi que les méthodes http GET,HEAD et POST. Placée sur une classe controller, elle permet de définir la politique de même origine pour une route particulière et sera appliqué à toutes les sous routes.

 

Il est bien sur possible de surcharger la politique sur une des méthodes de la classe Controller, afin d’effectuer une surcharge sur la configuration, par exemple si l’on souhaite autoriser une méthode en particulier et en exclure une autre.

Dans l’exemple ci dessus, seule la méthode GET /books/:id autorise une politique de même origine contraitement à la méthode DELETE /books/:id

Il est possible de configurer de manière globale la configuration du cross origin qui s’appliquera à l’ensemble des routes de l’application, evitant ainsi d’avoir à poser l’annotation @CrossOrigin sur l’ensemble des Controller:

Il est evidemment possible d’etre beaucoup plus précis:

 

C) @CrossOrigin + Spring Boot ?

Le support CORS à été ajouté dans la version 1.3 de Spring Boot. Il est toujours possible d’utiliser l’annotation @CrossOrigin en complément mais la configuration globale est en  revanche légèrement différente: