Lorsqu’on développe une application RESTful exploitant des webservices disponibles sur un autre domaine, on est rapidement confronté à des questions de sécurité, notamment le cross-site scripting (XSS).
Le problème
Le cas typique dans lequel on rencontre cette problématique est celui d’un site mobile « m.domaine.com » qui récupère des données sur le site desktop « domaine.com ». Toutes les requêtes Ajax partant de « m.domaine.com » vers « domaine.com » seront bloquées par la règle de sécurité Same Origin Policy.
La solution
La solution à cette problématique est le mécanisme du Cross-origin resource sharing (CORS) spécifié par le W3C et utilisable dans Apache et dans la plupart des navigateurs modernes.
La configuration Apache
Le vhost du domaine cible des requêtes (« domaine.com » dans notre exemple) doit spécifier des directives « Access-Control-Allow » :
<VirtualHost *:80> ServerName domaine.com Header set Access-Control-Allow-Origin "http://m.domaine.com" Header set Access-Control-Allow-Credentials true Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT" Header set Access-Control-Allow-Headers "content-type, accept, set-cookie" </VirtualHost>
Astuce
Grâce à la directive « Access-Control-Allow-Headers », on peut indiquer quels entêtes HTTP seront transmis. En autorisant « set-cookie », on peut récupérer, sur « m.domaine.com », le cookie d’une session ouverte sur « domaine.com ». Ainsi, on réalise facilement un petit SSO maison !
Les requêtes Ajax
Avec jQuery, la requête Ajax devra contenir le flag withCredentials à true dans les paramètres xhrFields (voir également la doc de XMLHttpRequest
pour les autres implémentations).
$.ajax({ url: 'http://domaine.com', xhrFields: { withCredentials: true } });
Attention à la subtilité !
On trouve très souvent la syntaxe ci-dessous :
Header set Access-Control-Allow-Origin "*"
Cette directive ne fonctionne pas lorsqu’on passe le flag withCredentials à true dans les paramètres xhrFields de la requête Ajax. Dans ce cas, il faut préciser explicitement le domaine autorisé :
Header set Access-Control-Allow-Origin "http://m.domaine.com"