Amazon S3 CORS (Kaynaklar Arası Kaynak Paylaşımı) ve Firefox alanlar arası yazı tipi yükleme


135

Firefox'un mevcut web sayfasından farklı bir kökene ait yazı tipini yüklememesiyle ilgili uzun süredir devam eden bir sorun var. Sorun genellikle yazı tipleri CDN'lerde sunulduğunda ortaya çıkar.

Diğer sorularda çeşitli çözümler ortaya atıldı:

CSS @ font-face Firefox ile çalışmıyor, ancak Chrome ve IE ile çalışıyor

Amazon S3 CORS ile birlikte, Firefox'taki yazı tipi yükleme sorununu çözmek için CORS kullanan bir çözüm var mı?

düzenleme: S3 CORS yapılandırmasının bir örneğini görmek harika olurdu.

edit2: Ne yaptığını gerçekten anlamadan çalışan bir çözüm buldum. Herhangi biri yapılandırmalar ve Amazon'un yapılandırmayı yorumlamasında meydana gelen arka plan büyüsü hakkında daha ayrıntılı açıklamalar sunabilirse, bunun için bir ödül koyan nzifnab'da olduğu gibi çok takdir edilecektir.

Yanıtlar:


148

10 Eylül 2014 güncellemesi:

Cloudfront artık CORS'u doğru bir şekilde desteklediğinden, aşağıdaki sorgu dizisi hack'lerinden herhangi birini yapmanız gerekmiyor. Daha fazla bilgi için http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/ ve bu yanıta bakın : https://stackoverflow.com/a/25305915/308315


Tamam, nihayet yazı tiplerini aşağıdaki yapılandırmayı kullanarak dokümantasyondaki örneklerden biraz ince ayar yaparak çalıştırdım.

Yazı tiplerim S3'te barındırılıyor, ancak önü cloudfront'ta bulunuyor.

Neden işe yaradığından emin değilim, tahminim muhtemelen bu <AllowedMethod> GETve <AllowedHeader> Content-*gerekli.

Amazon S3 CORS yapılandırmasında uzman biri bu konuya ışık tutabilirse, çok memnun kalacaktır.

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

Düzenle:

Bazı geliştiriciler, Cloudfront'un Access-Control-Allow-Originüstbilgiyi önbelleğe alma sorunlarıyla karşı karşıyadır . Bu sorun, @ Jeff-Atwood tarafından yorumlanan aşağıdaki bağlantıda ( https://forums.aws.amazon.com/thread.jspa?threadID=114646 ) AWS personeli tarafından ele alınmıştır .

Bağlantılı iş parçacığından, geçici çözüm olarak, farklı etki alanlarından gelen çağrıları ayırt etmek için bir Sorgu Dizesi kullanılması önerilir . Kısaltılmış örneği burada yeniden oluşturacağım.

curlYanıt başlıklarını kontrol etmek için kullanma :

Alan A: a.domain.com

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

Etki Alanı A'dan yanıt başlıkları:

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

Alan B: b.domain.com

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

Etki Alanı B'den yanıt başlıkları:

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

Access-Control-Allow-OriginCloudfront önbelleğe almayı aşan farklı değerler döndürdüğünü fark edeceksiniz .


2
Burada anlatılana benzer sorunlar yaşadınız mı - Access-Control-Allow-Originbaşlık önbelleğe alınır ve farklı bir alt alan üzerinden sonraki bir istek yapıldığında CORS geçersiz hale gelir mi?
ov

1
@ov Kaynakları kullanan etki alanlarını açıkça belirlediğim için bu sorunu yaşamıyorum. Daha önce gönderdiğiniz bağlantıyı okudum. Başka bir ileti dizisindeki bazı yanıtların etki alanlarının açıkça belirtilmesi gerektiğini söyleyen yanıtları belli belirsiz hatırladım, bu nedenle bazı kısıtlamalar nedeniyle <AllowedOrigin> * </AllowedOrigin> kullanımına fiilen izin verilmiyor. Bu yanıt gönderilerini şu anda bulamıyorum, başka bir yerde okuduğum blog yazısı olabilir. Umarım yardımcı olur.
VKen

3
Tek bir CORSRule öğesinin içinde birden fazla İzin Verilen Öğeye sahip olabilirsiniz, böylece bu CORS Kurallarını tek bir öğede birleştirebilirsiniz, çünkü içlerindeki diğer öğeler aynıdır.
Ben Hull

4
@dan S3 demeti CloudFront tarafından sunuluyorsa, yanıt, bu resmi Amazon yanıtında belgelendiği gibi yazı tipi sorgu dizesini
Jeff Atwood

2
Bu son derece sinir bozucu bir sorun oldu. İyi haber şu ki, S3 artık doğru şeyi yapıyor gibi görünüyor, bu nedenle en azından web yazı tiplerinden başka her şeyi CloudFront üzerinden sunmak ve yazı tipi dosyalarını doğrudan S3'ten sunmak mümkün. Ne yazık ki, sorgu dizesi hacklemesi uygulamamızda daha önemli bir yeniden düzenleme olmadan gerçekten pratik değildir, çünkü varlıkların tümü Rails varlık ardışık düzeni aracılığıyla sunulur ve varlık URL'lerini istek zamanında değiştirmenin uygun bir yolu yoktur (hepsi dağıtım sırasında oluşturulurlar) varlıklar önceden derlendiğinde). Yazı tipinin css'deki URL'si zaten S3'te.
Zach Lipton

97

Biraz ince ayar yaptıktan sonra, bunu sorgu dizisi kesmesi olmadan çalıştırdım. Daha fazla bilgi burada: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors

Tüm kurulumumu gözden geçireceğim, böylece ne yaptığımı görmek kolay, umarım bu başkalarına yardımcı olur.

Arka Plan Bilgileri: Varlıkları S3'e yerleştirmek için asset_sync gem'e sahip bir Rails uygulaması kullanıyorum. Bu, yazı tiplerini içerir.

S3 konsolunda, burada klasörüme, özelliklerime ve 'cors yapılandırmasını düzenle'ye tıkladım: CORS yapılandırma düğmesi

Metin alanının içinde şöyle bir şey var:

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

Ardından Cloudfront panelinde ( https://console.aws.amazon.com/cloudfront/home ) bir dağıtım oluşturdum, S3 işaret eden bir Origin ekledim bir başlangıç ​​noktası eklemek

Ardından, S3 tabanlı başlangıç ​​noktası kurulumuna işaret etmek için varsayılan bir yol için bir davranış eklendi. Ayrıca Beyaz Liste başlıklarına tıklamak ve ekledimOrigin : davranış ve beyaz liste başlıkları ekleme

Şimdi olan şey şudur ki bunun doğru olduğuna inanıyorum:

1) S3 başlıklarının doğru ayarlanıp ayarlanmadığını kontrol edin

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) Cloudfront'un üstbilgilerle çalıştığını kontrol edin

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

(Bu dosyalar 180 saniye önbelleğe alındığından, ancak aynı şeyin isabetler üzerinde de çalıştığı için, yukarıdakinin cloudfront'ta eksik olduğunu unutmayın)

3) Cloudfront'u farklı bir kaynakla vurun (ancak S3 demeti için CORS'da izin verilen bir kaynak) - Access-Control-Allow-Originönbelleğe alınmaz! Yaşasın!

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

Yukarıda, alan adının bir sorgu dizesi saldırısı olmadan başarıyla değiştirildiğini unutmayın.

Origin başlığını değiştirdiğimde, her zaman X-Cache: Miss from cloudfrontilk istekte bir var gibi görünüyor ve ardından beklenen şeyi alıyorumX-Cache: Hit from cloudfront

Not: curl -I (büyük harf I) yaparken, Access-Control-Allow-Origin başlıklarını yalnızca bir BAŞLIK olarak GÖSTERMEYECEĞİNİ, bunu bir GET haline getirmek ve yukarı kaydırmak için -i yapıyorum.


Diğerleri çalışmadığında çalıştı. Bu kadar ayrıntılı gönderi paylaşmaya zaman ayırdığınız için teşekkürler!
2014,

İşe yarıyor!! Bilginize - Bunu test ederken çok büyük bir http yanıt metnim vardı ... cevabı bu curl çözümünü kullanmak için düzenleyeceğim ... stackoverflow.com/questions/10060098/…
Michael Gorham

Harika teşekkürler çocuklar - bunun başkaları için işe yaradığını görmekten memnunum.
Eamonn Gahan

Bize ne kadar yardım ettiğinizi anlatamam! +1
özel bir şey yok

1
OriginGörüntüleyenlerden müşteri başlığını eklemek için +1, böylece Cloudfront nesneyi bu başlığa göre önbelleğe alır (ve sunucu CORS başlıklarını kullanıcıya geri iletir)
Sébastien Saunier

13

Yazı tiplerim, Heroku'ya yapılan son itişe kadar doğru bir şekilde sunuldu ... Nedenini bilmiyorum, ancak CORS'un izin verdiği kaynaktaki joker karakter çalışmayı durdurdu. Tüm prepro ve pro alan adlarımı klasör ayarındaki CORS politikasına ekledim , bu yüzden şimdi şöyle görünüyor:

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

Güncelleme: eklemek http://localhost:PORTçok


1
Bu çözümü paylaştığınız için teşekkür ederiz. Bu benim için çalıştı.
Ryan Montgomery

8

Belgeler, yapılandırmayı "paketinizdeki cors alt kaynağı" olarak yapıştırabileceğinizi belirtir. Bunu, yapılandırmayla paketimin kökünde "cors" adlı bir dosya oluşturacağım anlamına geldim, ancak bu işe yaramayacaktı. Sonunda Amazon S3 yönetim alanına giriş yapmam ve yapılandırmayı klasörümün propertiesiletişim kutusuna eklemem gerekiyordu.

S3 daha iyi belgeler kullanabilir ...


1
Evet, ancak özellikler panelinde bazı yeni arayüz değişiklikleri fark ettiğim için şanslıydım. Kova politikalarını düzenliyordum, bu yüzden doğal olarak aynı panelde CORS yapılandırmasını arıyorum.
VKen

benim için çalıştı, bu kadar basit olacağını bilen uygulamamda bunu ayarlamak
istiyordum

7

Amazon S3 CORS yapılandırmasında (S3 Bucket / İzinler / CORS) şunu kullanıyorsanız:

<?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, Javascript ve CSS dosyaları için iyi çalışır, ancak Yazı Tipi dosyaları için çalışmaz .

@VKen yanıtında belirtilen kalıbı kullanarak CORS'a izin vermek için etki alanını belirtmeniz gerekir: https://stackoverflow.com/a/25305915/618464

Öyleyse, şunu kullan :

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

Etki alanınız için "alanadim.com" u değiştirmeyi unutmayın.

Bundan sonra , CloudFront önbelleğini geçersiz kılın (CloudFront / Invalidations / Create Invalidation) ve çalışacaktır.


6

Benim durumumda, CORS yapılandırmasında XML ad alanını ve sürümünü tanımlamadım. İşe yarayanları tanımlamak.

değişmiş

<CORSConfiguration>

için

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

Benim için de çalışıyor. Yazı tiplerim paketin kendisinde barındırılıyor.
khamaileon

Varsayılan şablon neden bunu otomatik olarak içermiyor?
CoatedMoose

4

Daha iyi ve daha kolay bir yol var!

Bu sorunu çözmek için kişisel olarak DNS alt alanlarımı kullanmayı tercih ediyorum. CDN'im sdf73n7ssa.cloudfront.net yerine cdn.myawesomeapp.com'un arkasındaysa, tarayıcılar etki alanları arası güvenlik sorunları olarak onları çıldırmayacak ve engellemeyecektir.

Alt alanınızı AWS Cloudfront alanınıza yönlendirmek için AWS Cloudfront kontrol paneline gidin, Cloudfront dağıtımınızı seçin ve CDN alt alanınızı Alternatif Alan Adları (CNAME'ler) alanına girin. Cdn.myawesomeapp.com gibi bir şey yapacak.

Artık DNS sağlayıcınıza (AWS Route 53 gibi) gidebilir ve cdn.myawesomeapp.com için sdf73n7ssa.cloudfront.net'e işaret eden bir CNAME oluşturabilirsiniz.

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


Bu, SSL'yi kırar veya daha doğrusu SSL ile yapmak çok pahalıya mal olur, bu nedenle birçok insan bunu yapmaz.
maletor

4

Bu konfigürasyon benim için çalıştı. Nesneyi listeleyebilir, alabilir, güncelleyebilir ve silebilirim.

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

localhost'tan test ettiğim için alan adını değiştirmeniz gerekiyor, CORS için şu sayfaya bakın: docs.aws.amazon.com/AWSJavaScriptSDK/guide/…
Shahid

1
<ifModule mod_headers.c>

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

</ifModule>

Basit Çözüm


Paylaşım için teşekkürler! Bana tıpkı bu başlığı eklemek için fikir verdi 'meta veri' ise yükleme statik varlıklar bulut depolama. (Bu şekilde yalnızca 1 particular domainveya ile çalışacak olsa da all domains)
Vinay Vissh

0

Spring boot uygulamamı (server) yeniden başlatmak sorunu benim için çözdü.

CORS'u S3 üzerinde doğru şekilde yapılandırmıştım. Curl, kaynak başlık ile doğru yanıtı veriyordu. Safari, yazı tipini doğru bir şekilde alıyordu. CORS'yi kabul etmeye istekli olmayan yalnızca kromdu.

Davranışa tam olarak neyin neden olduğundan emin değilim. If-modifiye-since ile yapılacak bir şey olmalı


0

Bu yazı tipleriyle ilgili değil, resimlerle ilgili, uç bir durum olabilir, ama bana olduğu gibi, bir başkasının da başına gelebilir. Birine yardımcı olacağını umarak bunu burada bırakacağım:

"Söyledikleri her şeyi yaptım ama yine de çalışmıyor" senaryosundaysanız, muhtemelen Chrome ve Safari'de önbellekle ilgili bir sorundur. Sunucunuzun uygun bir CORS yapılandırma kümesine sahip olduğunu varsayalım:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
    </CORSRule>
</CORSConfiguration>

ve Firefox'ta her şey iyi çalışıyor, ancak Chrome ve Safari'de çalışmıyor. Uzak görüntü yolunuza hem basit bir yoldan erişiyorsanız<img src="http://my.remote.server.com/images/cat.png"> etiketten hem de bir js Görüntü öğesi src'den aşağıdaki şekilde :

var myImg = new Image()
myImg.crossOrigin = 'Anonymous'
myImg.onload = () => {
  // do stuff (maybe draw the downloaded img on a canvas)
}
myImg.src = 'http://my.remote.server.com/images/cat.png'

Sen elde edebileceğimiz No 'Access-Control-Allow-Origin'Chrome ve Safari hatayı. Bunun nedeni, ilkinin <img>tarayıcı önbelleğini bir şekilde bozması ve aynı görüntüye daha sonra (kod içi Görüntü öğesinde) erişmeye çalıştığınızda, yalnızca kırılmasıdır. Bundan kaçınmak için, tarayıcıyı görüntüyü yeniden istemeye zorlamak ve önbellek kullanmaktan kaçınmak için bir .src yoluna hayali bir GET parametresi ekleyebilirsiniz, örneğin:

<img src="http://my.remote.server.com/images/cat.png?nocache=true"></img>

-1

Evet tabi ki. Firefox, tıpkı http://dev.w3.org/csswg/css3-fonts/#allowing-cross-origin-font-loading adresindeki spesifikasyonun gerektirdiği gibi yazı tipleri için CORS'u destekler


Hızlı yanıtınız için teşekkürler Boris Zbarsky. S3 CORS ayarları için bazı örnek yapılandırmaları gösterebilecek misiniz?
VKen

S3'ü yapılandırmaya hiç bakmadım ... HTTP düzeyinde ne göndereceğime gelince, sorun değilse, sadece yazı tipi dosyaları için HTTP yanıtına "Access-Control-Allow-Origin: *" gönderiyor çalışmalı.
Boris Zbarsky

Teşekkürler, bu ayarın S3 CORS yapılandırmalarıyla tam olarak nasıl yapılacağını bulmaya çalışıyorum.
VKen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.