Les requêtes HTTP de type Cross-site sont des requêtes pour des ressources localisées sur un domaine différent de celui à l'origine de la requête. Par exemple, une ressource chargée depuis le domaine A (https://domaina.example
) comme une page HTML, effectue une requête pour une ressource provenant du domaine B (https://domainb.foo), comme une image, en utilisant la balise img
(https://domainb.foo/image.jpg
). C'est régulièrement le cas aujourd'hui sur le web — des pages chargent un nombre de ressources à la manière Cross-site, en ce inclus des feuilles de style (CSS), des images, des scripts, et d'autres ressources.
Les requêtes HTTP croisées initiées au départ de scripts ont été sujettes à des restrictions bien connues et pour des raisons de sécurité bien compréhensibles. Par exemple les requêtes HTTP effectuées par l'objet XMLHttpRequest
sont soumises à la politique de même origine. En particulier, cela signifiait qu'une application web utilisant XMLHttpRequest
ne pouvait que créer des requêtes HTTP vers le domaine d'où elle avait été chargée et non vers d'autres domaines. Les développeurs ont exprimé le désir de voir évoluer en toute sécurité les possibilités comme celles du XMLHttpRequest
afin d'effectuer des requêtes croisées (cross-site), pour de meilleures et plus sûres compositions au sein d'applications web.
Le Web Applications Working Group au sein du W3C a recommandé le nouveau mécanisme de Cross-Origin Resource Sharing qui fournit un moyen aux serveurs web de contrôler les accès en mode cross-site et aussi d'effectuer des transferts de données sécurisés en ce mode. Il est particulièrement intéressant de noter que cette spécification est utilisée au sein d'un API container comme le XMLHttpRequest
et ce en tant que mécanisme de mitigation, permettant de passer outre la restriction des navigateurs modernes de fonctionner sur base d'une politique "same-domain". L'information contenue dans cet article est intéressante pour les administrateurs web, les programmeurs de serveurs et les développeurs web. Un autre article pour les programmeurs serveurs discutant le partage des origines croisées sous l'angle du serveur (avec des extraits de code PHP) constitue une lecture supplémentaire fructueuse. Sur l'environnement client, le navigateur s'occupe de partager l'origine des ressources, incluant les entêtes et la mise en application de la politique générale en la matière. En revanche, l'introduction de cette nouvelle possibilité implique nécessairement que les serveurs doivent gérer de nouvelles entêtes, et doivent renvoyer les ressources avec de nouvelles entêtes également.
Ce standard de partage d'origines croisées est utilisé pour permettre les requêtes HTTP en mode cross-site pour:
- Les invocations de l'API
XMLHttpRequest
en mode cross-site comme présenté ci-avant. - Polices Web (pour l'utilisation au travers de domaines croisés avec la directive CSS
@font-face
), de sorte que les serveurs puissent déployer des polices TrueType qui ne puissent être chargées qu'en mode cross-site et chargées par les sites web à qui ceci est permis. - Textures WebGL.
- Images dessinées dans un canvas utilisant drawImage.
Cet article est une discussion générale du partage des ressources d'origines croisées et inclut une discussion du traitement des entêtes HTTP en Firefox 3.5.
Vue générale
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. Par ailleurs, pour les requêtes HTTP dont les méthodes pourraient avoir des effets secondaires sur les données utilisateur (en particulier pour les méthodes HTTP autres que GET
, ou pour l'utilisation du POST
avec certains types MIME), la spécification mandate les navigateurs pour "pré-vérifier" la requête en sollicitant le serveur pour connaître les méthodes approuvées. Cette pré-vérification s'effectue avec la méthode HTTP OPTIONS
, et ensuite, après "approbation" du serveur, envoit la requête véritable. Les serveurs peuvent aussi notifier les clients de ce que les permissions (incluant les cookies et les données d'authentification HTTP) doivent être envoyées avec les requêtes.
Les sections suivantes discutent des scenarios, autant que de la décomposition des entêtes utilisés.
Exemples de scenarios de contrôles d'accès
Ici, nous présentons 3 scenarios qui illustrent le fonctionnement du partage de ressources d'origines croisées. Tous ces exemples font usage de l'objet XMLHttpRequest
, qui peut être utilisé pour invoquer du cross-site dans n'importe quel navigateur qui le supporte.
Les fragments de JavaScript qui sont inclus dans ces sections (et les occurrences tournant du côté du serveur qui gèrent ces demandes d'origines croisées) peuvent peuvent être consultées "en action" ici, et fonctionneront dans les navigateurs qui supportent les origines croisées via l'objet XMLHttpRequest
. Une discussion du partage de ressources croisées dans la perspective serveur (en ce inclus les extraits PHP) peut être consulté ici.
Requêtes simples
Une requête cross-site simple est une requête qui:
- N'utilise que les options GET, HEAD ou POST. Si POST est utlisé pour envoyer des données au serveur le Content-Type des données envoyé au serveur est soit
application/x-www-form-urlencoded
,multipart/form-data
, outext/plain.
- Ne positionne pas d'entêtes personnalisés avec la requête HTTP Request (comme par exemple
X-Modified
, etc.)
Par exemple, supposez que le contenu web sur le domaine https://foo.example
souhaite invoquer du contenu sur le domaine https://bar.other
. Un code de ce type pourrait être utilisé dans du JavaScript déployé sur foo.example:
var invocation = new XMLHttpRequest(); var url = 'https://bar.other/resources/public-data/'; function callOtherDomain() { if(invocation) { invocation.open('GET', url, true); invocation.onreadystatechange = handler; invocation.send(); } }
Voyons à présent ce que le navigateur va envoyer au serveur dans ce cas, et voyons ce que le serveur répond:
GET /resources/public-data/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: https://foo.example/examples/access-control/simpleXSInvocation.html Origin: https://foo.example HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml [XML Data]
Lines 1 - 10 sont les entêtes envoyés par Firefox 3.5. Notez que l'entête principal ici est l'entête Origin:
entête à la ligne 10 ici au-dessus, qui montre que l'invocation vient d'un contenu provenant du domaine https://foo.example
.
Lines 13 - 22 montrent que la réponse HTTP du serveur sur le domaine https://bar.other
. En réponse, le server renvoie une entête Access-Control-Allow-Origin:
, montrée ci-dessus en ligne 16. L'utilisation de l'entête Origin:
et de Access-Control-Allow-Origin:
montrent l'accès au protocle de contrôle dans sa forme la plus simple. Dans ce cas, le serveur répond avec un Access-Control-Allow-Origin: *
qui signifie que la ressource peut être accédée de n'importe quel domaine de manière croisée (cross-site). Si les propriétaires de la ressource sur https://bar.other
souhaitaient restreindre l'accès à la ressource au seul domaine https://foo.example
, ils enverraient :
Access-Control-Allow-Origin: https://foo.example
Notez que maintenant, aucun domaine autre que https://foo.example
(identifié par l'entête ORIGIN: dans la requête, comme à la ligne 10 ci-dessus) ne peut accéder la ressource d'une manière croisée (cross-site). L'entête Access-Control-Allow-Origin
devrait contenir la valeur qui a été envoyée dans l'entête Origin
de la requête.
Requêtes pré-vérifiées
Contrairement aux requêtes simples (discutées ci-avant), les requêtes prévérifiées ("preflighted requests", stricto sensu, les requêtes avant décollage) envoient d'abord une requête HTTP avec l'entête OPTIONS
dans la ressource souhaitée de l'autre domaine et cela en vue de déterminer si la véritable requête est sûre à envoyer. Les requêtes croisées entre site sont prévérifiées de cette manière parce qu'elles peuvent avoir des implications sur les données utilisateur. En particulier, une requête est prévérifiée si :
- elle utilise des méthodes autres que
GET, HEAD
ouPOST
. Aussi, siPOST
est utilisée pour envoyer des reqûetes de données avec un Content-Type autre queapplication/x-www-form-urlencoded
,multipart/form-data
, outext/plain
, par exemple si la requêtePOST
envoie au serveur un contenu utile XML en utilisantapplication/xml
outext/xml
, alors la requête est pré-vérifiée. - elle positionne des entêtes propres (ex: la requête utilise une entête comme
X-PINGOTHER
)
À partir de Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1), les encodages de données text/plain
, application/x-www-form-urlencoded
et multipart/form-data
peuvent aussi être envoyés en mode croisé (cross-site) sans prévérification. Avant cela, seul text/plain
pouvait être envoyé sans cette prévérification.
Un exemple de ce type d'invocation pourrait être:
var invocation = new XMLHttpRequest(); var url = 'https://bar.other/resources/post-here/'; var body = '<?xml version="1.0"?><person><name>Arun</name></person>'; function callOtherDomain(){ if(invocation) { invocation.open('POST', url, true); invocation.setRequestHeader('X-PINGOTHER', 'pingpong'); invocation.setRequestHeader('Content-Type', 'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); } ......
Dans l'exemple ci-dessus, la ligne 3 crée un corps XML à envoyer avec une requête de type POST
(ligne 8). Aussi, à la ligne 9, un entête "personnalisé" (c'est-à-dire non-standard) est positionné dans la requête HTTP (X-PINGOTHER: pingpong
). De tels entêtes ne sont pas spécifiés dans la documentation du protocole HTTP/1.1, mais sont en général bien utiles à des applications web. Puisque la requête (POST
) utilise un Content-Type application/xml
, et puisque un entête personnalisé est employé, cette requête est prévérifiée.
Jetons un oeil aux échanges complets entre le client et le serveur:
OPTIONS /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Origin: https://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER Access-Control-Max-Age: 1728000 Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain POST /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Referer: https://foo.example/examples/preflightInvocation.html Content-Length: 55 Origin: https://foo.example Pragma: no-cache Cache-Control: no-cache <?xml version="1.0"?><person><name>Arun</name></person> HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: https://foo.example Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload]
Lignes 1 - 12 ci-dessus: représentent la requête de pré-vérification avec l'entête OPTIONS
. Firefox 3.1 détermine s'il a besoin d'envoyer ceci sur base des paramètres de la requête que l'extrait de JavaScript avait utilisés, de telle sorte que le serveur puisse répondre s'il est acceptable d'envoyer la requête avec de tels paramètres. OPTIONS est une méthode HTTP/1.1 qui est utilisée pour déterminer de futures informations des serveurs, et est une méthode idempotente, ce qui signifie qu'elle ne peut être utilisée pour modifier la ressource. Notez qu'en sus, deux autres entêtes sont envoyés (lignes 11 et 12 respectivement):
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER
L'entête Access-Control-Request-Method
notifie le serveur, comme élément de la requête de pré-vérification, que lorsque la véritable requête est envoyée, elle sera sera envoyée avec la méthode POST
. L'entête Access-Control-Request-Headers
notifie le serveur que lorsque la véritable requête est envoyée elle le sera avec une entête X-PINGOTHER
personnalisée. Le serveur a maintenant l'opportunité de déterminer s'il souhaite accepter une requête dans ses circonstances.
Lignes 15 - 27 ci-dessus sont la réponse que le serveur renvoit indiquant que la méthode de la requête (POST
) et les entêtes de la requête (X-PINGOTHER
) sont acceptables. En particulier, voyons les lignes 18-21:
Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER Access-Control-Max-Age: 1728000
Le serveur répond avec Access-Control-Allow-Methods
et indique que les méthodes POST
, GET
, et OPTIONS
sont des méthodes acceptables pour aller quérir la ressource en question. Notez que cet entête est similaire à l'entête de réponse HTTP/1.1 Allow, mais qu'il est utilisé de manière stricte dans le contexte du contrôle d'accès. Le serveur envoie aussi Access-Control-Allow-Headers
avec une valeur de X-PINGOTHER
, confirmant en cela que c'est un entête permis dans le cadre de la requête effective. Tout comme Access-Control-Allow-Methods
, Access-Control-Allow-Headers
est une liste séparée par des virgules d'entêtes acceptés. Enfin, Access-Control-Max-Age
indique la durée en secondes pendant laquelle la requête de pré-vérification peut être mise en cache sans qu'il soit nécessaire d'en envoyer une autre. Ici, 1728000 secondes est 20 jours.
Requêtes avec habilitations
La possibilité la plus intéressante exposée par l'objet XMLHttpRequest
et par le contrôle d'accès (Access Control) est de créer des requêtes habilitées qui ont connaissance des cookies HTTP et des informations d'authentification en HTTP. Par défaut, dans les invocations XMLHttpRequest
croisées (cross-site) les navigateurs ne vont pas envoyerles habilitations. Un tag spécifique doit être positionné dans l'objet XMLHttpRequest
quand il est invoqué.
Dans cet exemple, le contenu chargé originellement de https://foo.example
effecture une simple requête GET vers une ressource de https://bar.other
qui positionne les cookies. Le contenu dur foo.example peut contenir du JavaScript similaire à :
var invocation = new XMLHttpRequest(); var url = 'https://bar.other/resources/credentialed-content/'; function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send(); }
La ligne 7 montre la propriété de XMLHttpRequest
qui doit être positionnée pour rendre effective l'invocation avec les Cookies, pour ne pas la nommer la valeur logique withCredentials
. Par défaut, l'invocation est faite sans les Cookies. Comme il s'agit ici d'un requête GET
simple, elle n'est pas pré-vérifiée, mais le navigateur rejettera toute réponse qui n'a pas d'entête Access-Control-Allow-Credentials: true
, et NE RENDRA PAS disponible la réponse au contenu web qui l'a demandé.
Voyez ici un échantillon de l'change entre le client et le serveur:
GET /resources/access-control-with-credentials/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Referer: https://foo.example/examples/credential.html Origin: https://foo.example Cookie: pageAccess=2 HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:34:52 GMT Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2 X-Powered-By: PHP/5.2.6 Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Credentials: true Cache-Control: no-cache Pragma: no-cache Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 106 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain [text/plain payload]
Bien que la ligne 12 contienne le cookie destiné au contenu sur https://bar.other
, si bar.other ne répondait pas avec un Access-Control-Allow-Credentials: true
(ligne 20) la réponse serait ignorée et rendue indisponible. Note importante: quand on répond à une requête avec informations de compte, le serveur doit spécifier un domaine, et ne peut pas utiliser de jokers (wildcards). L'exemple ci-dessus échouerait si l'entête utilisait des jokers comme dans: Access-Control-Allow-Origin: *
. Puisque Access-Control-Allow-Origin
mentionne explicitement https://foo.example
, le contenu lié aux aspects de compte (credentials) est retourné au contenu web qui l'a demandé. Notez qu'à la ligne 23, un autre cookie est positionné.
Tous ces exemples peuvet être consultés en fonctionnement ici. La prochaine section traite des entêtes HTTP de manière plus précise.
Les entêtes HTTP de réponse
Cette section liste les entêtes de réponses HTTP que le serveur renvoie au sujet des requêtes contrôle d'accès (Access Control) comme définis par la spécification Cross-Origin Resource Sharing. La section précédent donne un aperçu de ceux-ci en action.
Access-Control-Allow-Origin
Une ressource peut renvoyer un entête Access-Control-Allow-Origin
avec la syntaxe suivante :
Access-Control-Allow-Origin: <origin> | *
Le paramètre origin
spécifie une URI qui peut accèder à la ressource. Le navigateur doit suivre cela. Pour une requête sans habilitations (credentials), le serveur peut spécifié "*" comme joker (wildcards), autorisant ainsi toutes origines à accèder à la ressource.
Par exemple, pour autoriser https://mozilla.com à accèder la ressource, vous pouvez spécifier:
Access-Control-Allow-Origin: https://mozilla.com
Access-Control-Expose-Headers
Requires Gecko 2.0(Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)Cette entête laisse le serveur mettre une liste blanche d'entêtes auquel le navigateur est autorisé à accèder. Par exemple:
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
Ceci autorise les entêtes X-My-Custom-Header
et X-Another-Custom-Header
à être présentés au navigateur.
Access-Control-Max-Age
Cette entête indique combien de temps les résultats peuvent être mis en cache. Pour un exemple de requête pré-vérifiée, allez voir les exemples au-dessus.
Access-Control-Max-Age: <delta-seconds>
Le paramètre delta-seconds
indique la durée en nombre de seconds durant lequel le résultat peut être caché.
Access-Control-Allow-Credentials
Cet entête indique si la réponse peut être ou non présentée lorsque le tag credentials
est vrai. Lorsqu'il est présent dans une réponse à une requête pré-vérifiée, cet entête indique si la requête peut être fait ou non en utilisant les habilitations (credentials). Notez que les requêtes GET simple ne sont pas pré-vérifiée, et par conséquent si une requête est faite sur une ressource avec des habilitations (credentials), si l'entête n'est pas renvoyé via la ressource, la réponse sera ignorée par le navigateur et non retournée au contenu web.
Access-Control-Allow-Credentials: true | false
Les requêtes d'habilitations Les requêtes d'habilitations sont détaillées plus haut.
Access-Control-Allow-Methods
Spécifie la méthode ou les méthodes autorisé lors de l'accès à la resource. Cet entête est utilisé en réponse à une requête pré-vérifiée. Les conditions sous lesquels une requête est pré-vérifiée sont discutées au-dessus.
Access-Control-Allow-Methods: <method>[, <method>]*
Un exemple de requête pré-vérifiée est donnée plus haut, avec un exemple qui envoie cet entête au navigateur.
Access-Control-Allow-Headers
Cet entête utilisé en réponse à une requête pré-vérifiée pour indiquer quels entêtes peuvent être utilisés lorsque la requête actuelle est faite.
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
Les entêtes HTTP de la requête
Cette section liste les entêtes que le client peuvent utiliser lorsqu'il crée des requête HTTP pour utiliser la fonctionnalité Cross-Origin Resource Sharing. Notez que les entêtes sont mis pour vous lorsque vous crée l'appel aux serveurs. Les développeurs qui utilise la fonction cross-site de XMLHttpRequest
ne doivent pas mettre, via le code, d'entête de requêtes cross-origing sharing .
Origine
Indique l'origine de la requête d'accès cross-site ou la requête pré-vérifiée.
Origin: <origin>
L'origine est l'URI qui indique le serveur depuis lequel la requête a été initié. Cela n'inclue pas l'information sur le chemin, mais uniquement le nom du serveur.
Notez que pour toutes requêtes de contrôle d'accès, l'entête ORIGIN
est toujours envoyé.
Access-Control-Request-Method
Cet entête utilisé lorsqu'une requête pré-vérifiée est émise pour faire connaitre au serveur quel méthode sera utilisé lorsque la requêtre actuelle sera faite .
Access-Control-Request-Method: <method>
Des exemples de cette usage peuvent être trouvés plus haut.
Access-Control-Request-Headers
Cet entête utilisé lorsqu'une requête pré-vérifiée est émise pour indiquer au serveur quels seront les entêtes HTTP utilisés lorsque sera fait la requête actuelle.
Access-Control-Request-Headers: <field-name>[, <field-name>]*
Des exemples de cette usage peuvent être trouvé plus haut.
Compatibilité navigateurs
Fonctionnalité | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Support simple | 4 | 3.5 | 8 (via XDomainRequest) 10 |
12 | 4 |
Fonctionnalité | Android | Chrome Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Support simple | 2.1 | yes | yes | ? | 12 | 3.2 |
Note
Internet Explorer 8 et 9 expose CORS via l'objet XDomainRequest, mais une implémentation complète est disponible dans IE 10. Lorsque Firefox 3.5 a introduit le support pour les requêtes XMLHttpRequests cross-site et les polices de caratères WEB, certaines requêtes ont été limité jusqu'à une version ultérieur. En particulier, Firefox 7 a introduit la capacité de faire des requêtes HTTP cross-site pour les textures WebGL, et Firefox 9 a ajouté le support pour les Images dessinées via le canvas en utilisant drawImage.
Voir aussi
- Code Samples Showing
XMLHttpRequest
and Cross-Origin Resource Sharing - Cross-Origing Resource Sharing From a Server-Side Perspective (PHP, etc.)
- Cross-Origin Resource Sharing specification
XMLHttpRequest
- Discussion à propos de l'entête Origin
- Using CORS with All (Modern) Browsers
- Using CORS - HTML5 Rocks