web-dev-qa-db-fra.com

Chargement de polices entre domaines dans Amazon S3 CORS (partage de ressources d'origine croisée) et Firefox

Il y a un problème de longue date avec Firefox qui ne charge pas les polices d'origine différente de la page Web actuelle. Généralement, le problème survient lorsque les polices sont servies sur des CDN.

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

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

Avec l'introduction de 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 bon de voir un échantillon de la configuration S3 CORS.

edit2: J'ai trouvé une solution qui fonctionne sans comprendre ce qu'elle a réellement fait. Si quelqu'un pouvait fournir des explications plus détaillées sur les configs et la magie de fond qui se produit lors de l'interprétation de la config par Amazon, ce serait grandement apprécié, comme pour nzifnab qui a mis une prime à sa place.

124
VKen

Mise à jour du 10 septembre 2014:

Vous ne devriez plus avoir à faire les hacks de la requête ci-dessous puisque Cloudfront prend correctement en charge CORS maintenant. 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 enfin réussi à faire fonctionner les polices en utilisant la configuration ci-dessous avec un petit Tweak à partir d’exemples dans la documentation.

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

Je ne sais pas pourquoi cela fonctionne, je suppose que les <AllowedMethod>GET et <AllowedHeader>Content-* sont nécessaires.

Si quelqu'un qui maîtrise la configuration d'Amazon S3 CORS peut éclaircir cette question, cela 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>

modifier:

Certains développeurs sont confrontés à des problèmes de mise en cache par Cloudfront de l'en-tête Access-Control-Allow-Origin. Le personnel AWS a traité ce problème dans le lien ( https://forums.aws.Amazon.com/thread.jspa?threadID=114646 ) ci-dessous, commenté par @ Jeff-Atwood.

Pour contourner le problème, il est conseillé d'utiliser une chaîne Query String pour différencier les appels de différents domaines. Je vais reproduire l'exemple abrégé ici.

Utilisation de 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 le Access-Control-Allow-Origin a renvoyé différentes valeurs, qui ont dépassé la mise en cache de Cloudfront.

139
VKen

Après quelques ajustements, il me semble que cela a fonctionné sans le piratage 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 parcourir toute ma configuration pour qu'il soit facile de voir ce que j'ai fait. J'espère que cela aidera les autres.

Informations de base: J'utilise une application Rails dotée de la gem asset_sync pour placer des actifs sur S3. Cela inclut les polices.

Dans la console S3, j'ai cliqué sur mon compartiment, mes propriétés et "modifier la configuration de cors", 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 pointait vers mon compartiment S3 adding an Origin

Ensuite, nous avons ajouté un comportement pour un chemin par défaut qui pointe vers la configuration Origin I basée sur S3. J'ai également cliqué sur les en-têtes de la liste blanche et ajouté Origin: adding a behavior and whitelist headers

Ce qui se passe maintenant est le suivant, que je crois avoir raison:

1) Vérifiez que les en-têtes S3 sont configurés correctement

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 était un échec de Cloudfront, car ces fichiers sont mis en cache pendant 180 secondes, mais le même problème fonctionnait pour les hits)

3) Hit Cloudfront avec une origine différente (mais celle qui est autorisée sur CORS pour le compartiment S3) - le Access-Control-Allow-Origin n'est pas mis en cache! Yay!

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 un hack de chaîne de requête.

Lorsque je change l'en-tête Origin, il semble toujours y avoir un X-Cache: Miss from cloudfront à la première demande, puis j'obtiens le X-Cache: Hit from cloudfront attendu.

P.S. Il est à noter que lorsque curl -I (capital I) ne montre PAS les en-têtes Access-Control-Allow-Origin car il s'agit uniquement d'un HEAD, je fais -i pour en faire un élément GET et le faire défiler vers le haut.

89
Eamonn Gahan

Mes polices ont été servies correctement jusqu'au dernier Push to Heroku ... Je ne sais pas pourquoi, mais le caractère générique dans la licence autorisée CORS Origin a cessé de fonctionner. J'ai ajouté tous mes domaines prepro et pro à la stratégie CORS dans les paramètres de compartiment afin qu'il 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>

UPDATE: ajoutez également votre http://localhost:PORT

13
luigi7up

Eh bien, la documentation indique que vous pouvez coller la configuration en tant que "sous-source cors dans votre compartiment". Je pensais que cela signifierait que je créerais un fichier appelé "cors" à la racine de mon compartiment avec la configuration, mais cela ne fonctionnerait pas. En fin de compte, j'ai dû me connecter à la zone d'administration Amazon S3 et ajouter la configuration dans la boîte de dialogue properties de mon compartiment.

S3 pourrait utiliser une meilleure documentation ...

8
nzifnab

Dans mon cas, je n'avais pas défini d'espace de noms XML ni de version dans la configuration CORS. Définir ceux qui ont travaillé.

Modifié

<CORSConfiguration>

à

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

Cette configuration a fonctionné pour moi. Je peux lister des objets, récupérer, mettre à jour et supprimer.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>http://localhost:3000</AllowedOrigin>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    <ExposeHeader>ETag</ExposeHeader>
    <ExposeHeader>x-amz-meta-custom-header</ExposeHeader>
  </CORSRule>
</CORSConfiguration>
4
Shahid

Il existe un moyen meilleur et plus simple!

Personnellement, je préfère utiliser mes sous-domaines DNS pour résoudre ce problème. Si mon CDN est derrière cdn.myawesomeapp.com au lieu de sdf73n7ssa.cloudfront.net, les navigateurs ne vont pas paniquer et les bloquer en tant que problèmes de sécurité interdomaines.

Pour faire pointer votre sous-domaine sur votre domaine AWS Cloudfront, accédez au panneau de configuration AWS Cloudfront, sélectionnez votre distribution Cloudfront et entrez votre sous-domaine CDN dans le champ Noms de domaine alternatifs (CNAME). Quelque chose comme cdn.myawesomeapp.com fera.

Vous pouvez maintenant accéder à votre fournisseur DNS (comme AWS Route 53) et créer un CNAME pour cdn.myawesomeapp.com pointant vers sdf73n7ssa.cloudfront.net.

http://blog.cloud66.com/cross-Origin-resource-sharing-cors-blocked-for-cloudfront-in-Rails/

4
msroot

Dans la configuration Amazon S3 CORS (S3 Bucket/Permissions/CORS) si vous utilisez ceci:

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

CORS fonctionne bien pour les fichiers Javascript et CSS, mais Il ne fonctionne pas pour les fichiers de police.

Vous devez spécifier le domaine pour permettre à CORS d'utiliser le modèle exprimé dans la réponse @VKen: https://stackoverflow.com/a/25305915/618464

Alors, utilisez ceci:

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

N'oubliez pas de remplacer "mydomain.com" pour votre domaine.

Après cela, invalide le cache CloudFront (CloudFront/Invalidations/Create Invalidation) et cela fonctionnera.

3
educoutinho
<ifModule mod_headers.c>

   Header set Access-Control-Allow-Origin: http://domainurl.com

</ifModule>

Solution simple

1
O-mkar

Redémarrer mon application Spring Boot (serveur) a résolu le problème pour moi.

J'avais configuré CORS correctement sur S3 . La boucle donnait la réponse correcte avec l'en-tête Origin . Safari récupérait la police correctement . Seul le chrome qui ne voulait pas accepter la CORS.

Vous ne savez pas exactement ce qui a provoqué le comportement . Doit avoir quelque chose à voir avec If-modified-since

0
Sujit Kamthe