it-swarm.com.de

Amazon S3 CORS (Cross-Origin Resource Sharing) und Firefox-domänenübergreifendes Laden von Schriftarten

Es gibt ein seit langem bestehendes Problem, dass Firefox keine Schriftart aus einem anderen Ursprung als der aktuellen Webseite lädt. Normalerweise tritt das Problem auf, wenn die Zeichensätze auf CDNs bereitgestellt werden.

In anderen Fragen wurden verschiedene Lösungen angesprochen:

CSS @ font-face funktioniert nicht mit Firefox, sondern mit Chrome und IE

Gibt es mit der Einführung von Amazon S3 CORS eine Lösung, die CORS verwendet, um das Problem beim Laden von Schriftarten in Firefox zu lösen?

edit: Es wäre toll, ein Beispiel der S3 CORS-Konfiguration zu sehen.

edit2: Ich habe eine funktionierende Lösung gefunden, ohne wirklich zu verstehen, was sie getan hat. Wenn jemand detailliertere Erklärungen zu den Configs und der Hintergrundmagie liefern könnte, die bei der Interpretation der Config durch Amazon auftreten, wird es sehr geschätzt, wie bei Nzifnab, der eine Belohnung dafür aufstellt.

124
VKen

Update 10. September 2014:

Sie sollten keine der folgenden Abfragezeichenfolge-Hacks mehr benötigen, da Cloudfront CORS jetzt ordnungsgemäß unterstützt. Siehe http://aws.Amazon.com/blogs/aws/enhanced-cloudfront-customization/ und diese Antwort für weitere Informationen: https://stackoverflow.com/a/25305915/308315


OK, ich habe endlich die Fonts mit der untenstehenden Konfiguration mit ein wenig Tweak von Beispielen in der Dokumentation zum Laufen gebracht.

Meine Schriften werden auf S3 gehostet, jedoch vor Cloudfront.

Ich bin nicht sicher, warum es funktioniert. Ich vermute, dass <AllowedMethod>GET und <AllowedHeader>Content-* benötigt werden.

Wenn jemand, der sich mit Amazon S3 CORS config auskennt, etwas Licht ins Dunkel bringen kann, wird es sehr geschätzt.

<?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>

bearbeiten:

Einige Entwickler haben Probleme mit Cloudfront, die den Access-Control-Allow-Origin-Header zwischenspeichern. Dieses Problem wurde von den Mitarbeitern von AWS in dem folgenden Link ( https://forums.aws.Amazon.com/thread.jspa?threadID=114646 ) behoben, kommentiert von @ Jeff-Atwood.

Es wird empfohlen, aus dem verknüpften Thread als Abhilfemaßnahme einen Query String zu verwenden, um zwischen Aufrufen aus verschiedenen Domänen zu unterscheiden. Ich werde das verkürzte Beispiel hier wiedergeben.

Antwortheader mit curl prüfen:

Domäne A: a.domain.com

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

Antwortheader aus Domäne 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

Domäne B: b.domain.com

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

Antwortheader aus Domäne 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

Sie werden feststellen, dass Access-Control-Allow-Origin andere Werte zurückgegeben hat, die über das Cloudfront-Caching hinausgingen.

139
VKen

Nach einigen Optimierungen schien es mir gelungen zu sein, ohne den Abfrage-String-Hack zu funktionieren. Weitere Informationen hier: http://docs.aws.Amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors

Ich werde mein gesamtes Setup durchgehen, damit ich leicht sehen kann, was ich getan habe. Hoffentlich hilft das anderen.

Hintergrundinformationen: Ich verwende eine Rails-App, die über das Asset asset_sync verfügt, um Assets auf S3 zu setzen. Dies beinhaltet Schriftarten.

Innerhalb der S3-Konsole habe ich auf mein Bucket, meine Eigenschaften und die "Konfiguration der Korsik" geklickt, hier: CORS config button

Im Textbereich habe ich so etwas wie:

<?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>

Dann erstellte ich im Cloudfront-Panel ( https://console.aws.Amazon.com/cloudfront/home ) eine Distribution und fügte einen Origin hinzu, der auf meinen S3-Bucket zeigte adding an Origin

Anschließend wurde ein Verhalten für einen Standardpfad hinzugefügt, der auf das S3-basierte Origin I-Setup verweist. Ich habe auch auf Whitelist-Header geklickt und Origin: .__ hinzugefügt.adding a behavior and whitelist headers

Was jetzt passiert, ist folgendes, was ich für richtig halte:

1) Prüfen Sie, ob die S3-Header korrekt eingestellt sind

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) Überprüfen Sie, ob Cloudfront mit den Headern funktioniert

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==

(Beachten Sie, dass das obige Problem von Cloudfront nicht erfüllt wurde, da diese Dateien 180 Sekunden zwischengespeichert werden, das gleiche Ergebnis jedoch bei Treffern war.)

3) Schlagen Sie Cloudfront mit einem anderen Ursprung an (aber einer, der auf CORS für den S3-Bucket zulässig ist) - der Access-Control-Allow-Origin wird nicht zwischengespeichert! 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==

Beachten Sie oben, dass die Domäne erfolgreich ohne Abfragezeichenfolge-Hack geändert wurde.

Wenn ich den Origin-Header ändere, scheint es bei der ersten Anfrage immer einen X-Cache: Miss from cloudfront zu geben, danach bekomme ich den erwarteten X-Cache: Hit from cloudfront

P.S. Es ist erwähnenswert, dass wenn curl -I (capital I) NICHT die Access-Control-Allow-Origin-Header anzeigt, da es nur ein HEAD ist. Ich mache -i, um ein GET zu machen und nach oben zu scrollen.

89
Eamonn Gahan

Meine Schriften wurden bis zum letzten Push to Heroku korrekt bereitgestellt. Ich weiß nicht warum, aber die Platzhalter im CORS erlaubten, dass Origin nicht mehr funktioniert. Ich habe alle meine Präpro- und Pro Domains zu der CORS-Richtlinie in der Bucket-Einstellung hinzugefügt. Jetzt sieht es so aus:

<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: Fügen Sie auch Ihren http://localhost:PORT hinzu

13
luigi7up

Nun, in der Dokumentation heißt es, dass Sie die Konfiguration als "cors subresource in Ihrem Bucket" festlegen können. Ich nahm an, dass ich mit der Konfiguration eine Datei namens "cors" an der Wurzel meines Bucket erstellen würde, aber dies würde nicht funktionieren. Am Ende musste ich mich im Amazon S3-Administrationsbereich anmelden und die Konfiguration im properties-Dialog meines Bucket hinzufügen.

S3 könnte eine bessere Dokumentation gebrauchen ...

8
nzifnab

In meinem Fall hatte ich in der CORS-Konfiguration keinen XML-Namespace und keine Version definiert. Definieren der Gearbeiteten.

Geändert

<CORSConfiguration>

zu

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

Diese Konfiguration hat für mich funktioniert. Ich kann Objekte auflisten, abrufen, aktualisieren und löschen.

<?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

Es gibt einen besseren und leichteren Weg!

Ich persönlich bevorzuge die Verwendung meiner DNS-Subdomains, um dieses Problem zu lösen. Wenn sich mein CDN hinter cdn.myawesomeapp.com anstelle von sdf73n7ssa.cloudfront.net befindet, werden Browser nicht ausflippen und sie als domänenübergreifende Sicherheitsprobleme blockieren.

Um Ihre Subdomain auf Ihre AWS Cloudfront-Domäne zu verweisen, gehen Sie zum AWS Cloudfront-Steuerungsfeld, wählen Sie Ihre Cloudfront-Verteilung aus und geben Sie Ihre CDN-Subdomäne in das Feld Alternate Domain Names (CNAMEs) ein. So etwas wie cdn.myawesomeapp.com reicht aus.

Nun können Sie zu Ihrem DNS-Anbieter (wie AWS Route 53) gehen und einen CNAME für cdn.myawesomeapp.com erstellen, der auf sdf73n7ssa.cloudfront.net verweist.

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

4
msroot

In Amazon S3 CORS-Konfiguration (S3-Bucket/Permissions/CORS), wenn Sie Folgendes verwenden:

<?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 funktioniert gut für Javascript- und CSS-Dateien, aber funktioniert nicht für Font-Dateien.

Sie müssen die Domäne angeben, damit CORS das in der Antwort von @VKen angegebene Muster verwenden kann: https://stackoverflow.com/a/25305915/618464

Verwenden Sie dies:

<?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>

Denken Sie daran, "mydomain.com" für Ihre Domain zu ersetzen.

Danach wird den CloudFront-Cache ungültig machen (CloudFront/Invalidations/Invalidation erstellen) und es funktioniert.

3
educoutinho
<ifModule mod_headers.c>

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

</ifModule>

Einfache Lösung

1
O-mkar

Durch den Neustart meiner Spring Boot-Anwendung (Server) wurde das Problem für mich gelöst.

Ich hatte CORS korrekt auf S3 konfiguriert. Die Curl gab die richtige Antwort mit dem Origin-Header ab. Safari lieferte die Schriftart korrekt. Nur der Chrome war nicht bereit, die CORS zu akzeptieren.

Nicht sicher, was genau das Verhalten verursacht hat . Muss etwas mit If-modified-since zu tun haben

0
Sujit Kamthe