142 votes

Amazon S3 CORS (Cross-Origin Resource Sharing) et chargement de polices interdomaines pour Firefox

Il existe depuis longtemps un problème avec Firefox qui ne charge pas les polices provenant d'une origine différente de la page web actuelle. En général, le problème survient lorsque les polices sont servies par des CDN.

Diverses solutions ont été évoquées dans d'autres questions :

CSS @font-face ne fonctionne pas avec Firefox, mais fonctionne avec Chrome et IE

Avec l'introduction d'Amazon S3 CORS, existe-t-il une solution utilisant CORS pour résoudre le problème de chargement des polices dans Firefox ?

edit : Il serait intéressant de voir un exemple de la configuration S3 CORS.

edit2 : J'ai trouvé une solution qui fonctionne sans pour autant comprendre ce qu'elle fait. Si quelqu'un peut fournir des explications plus détaillées sur les configurations et la magie de fond qui se produit sur l'interprétation de la configuration par Amazon, ce sera grandement apprécié, comme avec nzifnab qui a mis en place un bounty pour cela.

152voto

VKen Points 2105

Mise à jour le 10 septembre 2014 :

Vous ne devriez plus avoir besoin d'utiliser les chaînes de requête ci-dessous, car Cloudfront prend désormais en charge CORS. Voir http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/ et cette réponse pour plus d'informations : https://stackoverflow.com/a/25305915/308315


OK, j'ai finalement réussi à faire fonctionner les polices en utilisant la configuration ci-dessous avec quelques modifications par rapport aux exemples de la documentation.

Mes polices sont hébergées sur S3, mais elles sont hébergées par cloudfront.

Je ne suis pas sûr de savoir pourquoi cela fonctionne, mais je pense que c'est probablement parce que les <AllowedMethod> GET y <AllowedHeader> Content-* est nécessaire.

Si quelqu'un de compétent en matière de configuration Amazon S3 CORS peut nous éclairer sur ce point, ce sera grandement apprécié.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>https://mydomain.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Content-*</AllowedHeader>
        <AllowedHeader>Host</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://*.mydomain.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Content-*</AllowedHeader>
        <AllowedHeader>Host</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

éditer :

Certains développeurs rencontrent des problèmes liés à la mise en cache par Cloudfront de l'élément Access-Control-Allow-Origin l'en-tête. Cette question a été abordée par le personnel de l'AWS dans le lien ( https://forums.aws.amazon.com/thread.jspa?threadID=114646 ) ci-dessous, commentée par @Jeff-Atwood.

D'après le fil de discussion cité, il est conseillé, comme solution de contournement, d'utiliser un Chaîne de requête pour différencier les appels provenant de différents domaines. Je reproduis ici l'exemple abrégé.

Utilisation curl pour vérifier les en-têtes de réponse :

Domaine A : a.domain.com

curl -i -H "Origin: https://a.domain.com" http://hashhashhash.cloudfront.net/font.woff?https_a.domain.com

En-têtes de réponse du domaine A :

Access-Control-Allow-Origin: https://a.domain.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
X-Cache: Miss from Cloudfront

Domaine B : b.domain.com

curl -i -H "Origin: http://b.domain.com" http://hashhashhash.cloudfront.net/font.woff?http_b.domain.com

En-têtes de réponse du domaine B :

Access-Control-Allow-Origin: http://b.domain.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
X-Cache: Miss from Cloudfront

Vous remarquerez que les Access-Control-Allow-Origin a renvoyé des valeurs différentes, qui ont échappé à la mise en cache de Cloudfront.

2 votes

Avez-vous rencontré des problèmes similaires à ceux décrits ci-dessus ? ici - les Access-Control-Allow-Origin est mis en cache et invalide CORS lorsqu'une requête ultérieure est effectuée via un sous-domaine différent ?

1 votes

@o.v. Je ne rencontre pas ce problème car j'ai explicitement défini les domaines qui utilisent les ressources. J'ai déjà lu le lien que vous avez posté. Je me souviens vaguement de réponses sur un autre fil de discussion disant que les domaines doivent être explicitement indiqués, de sorte que <AllowedOrigin>*</AllowedOrigin> n'est pas réellement autorisé, en raison de certaines restrictions. Je n'arrive pas à retrouver ces réponses maintenant, c'est peut-être un article de blog que j'ai lu ailleurs. J'espère que cela vous aidera.

3 votes

Il est possible d'avoir plusieurs éléments AllowedOrigin à l'intérieur d'un seul élément CORSRule, de sorte que vous pouvez combiner ces CORSRules en un seul élément, étant donné que les autres éléments qu'elles contiennent sont identiques.

104voto

Eamonn Gahan Points 61

Après quelques ajustements, il semble que j'ai réussi à faire fonctionner ce système sans l'utilisation de la chaîne de requête. Plus d'informations ici : http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors

Je vais passer en revue toute mon installation pour qu'il soit facile de voir ce que j'ai fait, en espérant que cela aidera d'autres personnes.

Informations générales : J'utilise une application Rails qui possède la gemme asset_sync pour placer des actifs sur S3. Cela inclut les polices.

Dans la console S3, j'ai cliqué sur mon bucket, properties et 'edit cors configuration', ici : CORS config button

Dans la zone de texte, j'ai quelque chose comme :

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>https://*.example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Ensuite, dans le panneau Cloudfront ( https://console.aws.amazon.com/cloudfront/home ) J'ai créé une distribution, ajouté une origine qui pointe vers mon panier S3 adding an origin

J'ai ensuite ajouté un comportement pour un chemin par défaut qui pointe vers l'origine basée sur S3 que j'ai configurée. J'ai également cliqué sur Whitelist headers et j'ai ajouté Origin : adding a behavior and whitelist headers

La situation actuelle est la suivante, et je pense qu'elle est correcte :

1) Vérifier que les en-têtes S3 sont correctement définis

curl -i -H "Origin: https://example.com" https://s3.amazonaws.com/xxxxxxxxx/assets/fonts/my-cool-font.ttf
HTTP/1.1 200 OK
x-amz-id-2: Ay63Qb5uR98ag47SRJ91+YALtc4onRu1JUJgMTU98Es/pzQ3ckmuWhzzbTgDTCt+
x-amz-request-id: F1FFE275C0FBE500
Date: Thu, 14 Aug 2014 09:39:40 GMT
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=180
Last-Modified: Mon, 09 Dec 2013 14:29:04 GMT
ETag: "98918ee7f339c7534c34b9f5a448c3e2"
Accept-Ranges: bytes
Content-Type: application/x-font-ttf
Content-Length: 12156
Server: AmazonS3

2) Vérifier que Cloudfront fonctionne avec les en-têtes

curl -i -H "Origin: https://example.com" https://xxxxx.cloudfront.net/assets/fonts/my-cool-font.ttf
HTTP/1.1 200 OK
Content-Type: application/x-font-ttf
Content-Length: 12156
Connection: keep-alive
Date: Thu, 14 Aug 2014 09:35:26 GMT
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=180
Last-Modified: Mon, 09 Dec 2013 14:29:04 GMT
ETag: "98918ee7f339c7534c34b9f5a448c3e2"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin
X-Cache: Miss from cloudfront
Via: 1.1 77bdacfea247b6cbe84dffa61da5a554.cloudfront.net (CloudFront)
X-Amz-Cf-Id: cmCxaUcFf3bT48zpPw0Q-vDDza0nZoWm9-_3qY5pJBhj64iTpkgMlg==

(Notez que ce qui précède a été manqué par cloudfront parce que ces fichiers sont mis en cache pendant 180 secondes, mais la même chose a fonctionné pour les hits).

3) Utiliser cloudfront avec une origine différente (mais qui est autorisée par CORS pour le seau S3) - le fichier Access-Control-Allow-Origin n'est pas mis en cache !

curl -i -H "Origin: https://www2.example.com" https://xxxxx.cloudfront.net/assets/fonts/my-cool-font.ttf
HTTP/1.1 200 OK
Content-Type: application/x-font-ttf
Content-Length: 12156
Connection: keep-alive
Date: Thu, 14 Aug 2014 10:02:33 GMT
Access-Control-Allow-Origin: https://www2.example.com
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Cache-Control: public, must-revalidate, proxy-revalidate, max-age=180
Last-Modified: Mon, 09 Dec 2013 14:29:04 GMT
ETag: "98918ee7f339c7534c34b9f5a448c3e2"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin
X-Cache: Miss from cloudfront
Via: 1.1 ba7014bad8e9bf2ed075d09443dcc4f1.cloudfront.net (CloudFront)
X-Amz-Cf-Id: vy-UccJ094cjdbdT0tcKuil22XYwWdIECdBZ_5hqoTjr0tNH80NQPg==

Notez ci-dessus que le domaine a été modifié avec succès sans qu'une chaîne de requête ne soit modifiée.

Lorsque je modifie l'en-tête Origin, il semble qu'il y ait toujours un X-Cache: Miss from cloudfront lors de la première demande, puis j'obtiens ensuite le résultat escompté X-Cache: Hit from cloudfront

P.S. Il est intéressant de noter qu'en faisant curl -I (I majuscule), les en-têtes Access-Control-Allow-Origin n'apparaîtront PAS car il s'agit seulement d'un HEAD, je fais -i pour que ce soit un GET et je fais défiler la page vers le haut.

1 votes

A fonctionné quand tous les autres n'ont pas fonctionné. Merci d'avoir pris le temps d'écrire un article aussi détaillé !

0 votes

Ça marche ! Pour info - j'ai eu un énorme texte de réponse http en testant ceci... je vais éditer la réponse pour utiliser cette solution curl... stackoverflow.com/questions/10060098/

0 votes

Cool, merci les gars - heureux de voir que cela fonctionne pour d'autres.

13voto

luigi7up Points 973

Mes polices ont été servies correctement jusqu'à la dernière poussée vers Heroku... Je ne sais pas pourquoi, mais le joker dans l'origine autorisée par CORS a cessé de fonctionner. J'ai ajouté tous mes prepro et pro à la politique CORS dans les paramètres du seau, de sorte que cela ressemble maintenant à ceci :

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>http://prepro.examle.com</AllowedOrigin>
        <AllowedOrigin>https://prepro.examle.com</AllowedOrigin>
        <AllowedOrigin>http://examle.com</AllowedOrigin>
        <AllowedOrigin>https://examle.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>

</CORSConfiguration>

MISE À JOUR : ajoutez votre http://localhost:PORT aussi

1 votes

Merci d'avoir partagé cette solution. Cela a fonctionné pour moi.

8voto

nzifnab Points 7542

La documentation indique qu'il est possible de coller la configuration comme "la sous-ressource cors dans votre seau". J'en ai déduit que je devais créer un fichier appelé "cors" à la racine de mon bac avec la configuration, mais cela n'a pas fonctionné. En fin de compte, j'ai dû me connecter à la zone d'administration d'Amazon S3 et ajouter la configuration dans le fichier properties dialogue de mon seau.

S3 pourrait bénéficier d'une meilleure documentation...

1 votes

Oui, mais j'ai eu la chance d'apercevoir de nouveaux changements d'interface dans le panneau des propriétés. J'ai modifié les politiques des seaux, et j'ai donc naturellement cherché la configuration CORS dans le même panneau.

0 votes

Cela a fonctionné pour moi, je cherchais à mettre cela en place dans mon application, qui aurait cru que ce serait si simple.

6voto

Gaurav Toshniwal Points 323

Dans mon cas, je n'avais pas défini l'espace de noms et la version XML dans la configuration CORS. La définition de ces éléments a fonctionné.

Modifié

<CORSConfiguration>

à

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">

0 votes

Cela me convient également. Mes polices sont hébergées sur le bucket lui-même.

0 votes

Je ne comprends pas pourquoi le modèle par défaut ne l'inclut pas automatiquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X