Amazon S3 CORS(クロスオリジンリソースシェアリング)およびFirefoxクロスドメインフォントのロード


134

Firefoxが現在のWebページとは異なるオリジンからフォントをロードしないという長い間問題がありました。通常、フォントがCDNで提供されるときに問題が発生します。

他の質問でさまざまな解決策が提起されました:

CSS @ font-faceはFirefoxでは機能しませんが、ChromeおよびIEでは機能します

Amazon S3 CORSの導入に伴い、CORSを使用してFirefoxのフォント読み込みの問題に対処するソリューションはありますか?

編集:S3 CORS構成のサンプルを見ていただければ幸いです。

edit2:私は実際にそれが何をしたのか理解せずに実用的な解決策を見つけました。構成とAmazonの構成の解釈で発生するバックグラウンドマジックについての詳細な説明を誰かが提供できれば、それに対する報奨金を上げたnzifnabのように、それは大いに感謝されます。

回答:


148

2014年9月10日更新:

CloudfrontがCORSを適切にサポートするようになったので、以下のクエリ文字列ハックを実行する必要はもうありません。詳細については、http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/およびこの回答を参照してくださいhttps : //stackoverflow.com/a/25305915/308315


わかりました。ドキュメントの例から少し調整して、以下の設定を使用してフォントを動作させました。

私のフォントはS3でホストされていますが、フロントはcloudfrontです。

なぜ機能するのかわかりませんが、おそらく<AllowedMethod> GET<AllowedHeader> Content-*が必要だと思います。

Amazon S3 CORSの設定に精通している人がこれにいくつかの光を当てることができれば、それは非常に高く評価されます。

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

編集:

一部の開発者は、Access-Control-Allow-OriginヘッダーをキャッシュするCloudfrontの問題に直面しています。この問題は、@ Jeff-Atwoodがコメントした下記のリンク(https://forums.aws.amazon.com/thread.jspa?threadID=114646)でAWSスタッフが対処しています。

リンクされたスレッドから、回避策として、クエリ文字列を使用して異なるドメインからの呼び出しを区別することをお勧めします。ここでは短縮した例を再現します。

を使用curlして応答ヘッダーを確認します。

ドメインA:a.domain.com

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

ドメイン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

ドメインB:b.domain.com

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

ドメイン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

Access-Control-Allow-OriginCloudfrontのキャッシュを通過したさまざまな値がによって返されたことに気づくでしょう。


2
あなたが記載されているものと同様の問題を経験していここを - Access-Control-Allow-Origin後続の要求が異なるサブドメインを介して行われたときにヘッダがキャッシュされ、無効化CORSを取得?
2012

1
@ovリソースを使用するドメインを明示的に設定したため、問題は発生しません。以前に投稿したリンクを読みました。ドメインを明示的に記述する必要があるという別のスレッドへの返信を漠然と覚えていたため、いくつかの制限のため、<AllowedOrigin> * </ AllowedOrigin>は実際には許可されていません。現在、これらの返信投稿は見つかりません。他の場所で読んだブログ投稿である可能性があります。お役に立てば幸いです。
VKen

3
単一のCORSRule要素内に複数のAllowedOrigin要素を含めることができます。それらの他の要素は同一であるため、それらのCORSRuleを単一の要素に結合できます。
ベン・ハル

4
@dan S3バケットがCloudFrontによって提供されている場合、この公式のAmazonの回答に記載されているように、ドメインごとにフォントクエリ文字列変えることが答えのようですforums.aws.amazon.com/thread.jspa?threadID
Jeff Atwood

2
これは非常にイライラする問題でした。良い知らせは、S3が現在正しく動作しているように見えるため、少なくともCloudFrontを介してWebフォント以外のすべてを提供し、S3から直接フォントファイルを提供することが可能です。悲しいことに、すべてのアセットはRailsアセットパイプラインを介して提供され、リクエスト時にアセットURLを微調整する便利な方法がないため、クエリ文字列ハックは、アプリケーションでの大幅なリファクタリングなしでは実際には実用的ではありません(すべてデプロイ時に生成されます)アセットがプリコンパイルされたとき)。css内のフォントのURLはすでにS3にあります。
Zach Lipton 2013

97

少し調整した結果、クエリ文字列をハックしなくても機能するようになりました。詳細はこちら:http : //docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors

私が行ったことを簡単に確認できるように、セットアップ全体を実行します。これが他の人の役に立つことを願っています。

背景情報:asset_sync gemが含まれているRailsアプリを使用して、アセットをS3に配置しています。これにはフォントが含まれます。

S3コンソール内で、バケット、プロパティ、および「cors構成の編集」をクリックしました。 CORS設定ボタン

テキストエリア内には次のようなものがあります:

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

次に、Cloudfrontパネル内(https://console.aws.amazon.com/cloudfront/home)でディストリビューションを作成し、S3バケットを指すOriginを追加しました 原点を追加する

次に、セットアップしたS3ベースのオリジンを指すデフォルトパスの動作を追加しました。また、ホワイトリストのヘッダーをクリックして追加しましたOrigin動作とホワイトリストヘッダーの追加

今、何が起こっているかは次のとおりです。

1)S3ヘッダーが正しく設定されていることを確認します

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がヘッダーで機能することを確認します

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

(これらのファイルは180秒間キャッシュされるため、上記はcloudfrontからのミスでしたが、同じことがヒットで機能していたことに注意してください)

3)異なるオリジン(ただし、S3バケットのCORSで許可されているもの)でcloudfrontをヒットします-これAccess-Control-Allow-Originはキャッシュされません!わーい!

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

上記は、クエリ文字列のハックなしでドメインが正常に変更されたことに注意してください。

Originヘッダーを変更するX-Cache: Miss from cloudfrontと、最初のリクエストに常にがあるようですが、その後、期待どおりになりますX-Cache: Hit from cloudfront

PS curl -I(大文字のI)を実行すると、Access-Control-Allow-OriginヘッダーはHEADだけなので表示されないことに注意してください。-iを実行して、GETにして上にスクロールします。


他のすべてがしなかったときに働いた。このような詳細を投稿していただきありがとうございます。
iwasrobbed 09/10/14

できます!!FYI -これをテストするとき、私は巨大なHTTP応答テキストを持っていた...つもり編集このカールソリューションを使用するには、答えは... stackoverflow.com/questions/10060098/...
マイケル・ゴーハム

みんな、ありがとうございました。他の人たちのために機能していることをうれしく思います。
Eamonn Gahan 2014

あなたがどれだけ私たちを助けてくれたのか、私には言えません!+1
特別なものはありません。ここ

1
顧客のヘッダを追加するための+1 OriginCloudFrontは、そのヘッダに基づいて、オブジェクトをキャッシュし(ユーザにサーバCORSヘッダーバックを転送する)ように視聴者から
セバスチャンSaunierの

13

Herokuへの最後のプッシュまで、フォントは正しく提供されていました...理由はわかりませんが、CORS許可のワイルドカードでワイルドカードが機能しなくなりました。preproドメインとproドメインをすべてバケット設定のCORSポリシーに追加したので、次のようになります。

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

更新:あなたhttp://localhost:PORTも追加


1
このソリューションを共有していただきありがとうございます。これでうまくいきました。
Ryan Montgomery

8

まあ、ドキュメントには、「バケット内のcorsサブリソース」として設定を固執できると記載されています。私はこれを、バケットのルートに「cors」という名前のファイルを構成とともに作成することを意味しますが、これは機能しません。最後に、Amazon S3管理エリアにログインしてproperties、バケットのダイアログ内に構成を追加する必要がありました。

S3はより良いドキュメントを使用できます...


1
ええ、でも幸運なことに、プロパティパネルで新しいインターフェースの変更点を見つけることができました。私はバケットポリシーを編集しているので、当然、同じパネルでCORS構成を探します。
VKen

私のために働いた、私はそれを自分のアプリケーションに設定することを探していた、それはそれがとても簡単であることを知っていた
Richlewis

7

Amazon S3 CORS構成(S3バケット/アクセス許可/ CORS)でこれを使用する場合:

<?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およびCSSファイルに対しては適切に機能しますが、フォントファイルに対しては機能しません

@VKen回答で表現されたパターンを使用してCORSを許可するには、ドメインを指定する必要があります。https://stackoverflow.com/a/25305915/618464

だから、これを使ってください:

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

ドメインの「mydomain.com」を忘れずに置き換えてください。

この後、CloudFrontキャッシュ(CloudFront / Invalidations / Create Invalidation)を無効にすると動作します。


6

私の場合、CORS構成でXML名前空間とバージョンを定義していませんでした。機能したものを定義します。

かわった

<CORSConfiguration>

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

私もうまくいきます。私のフォントはバケット自体でホストされています。
khamaileon 2014

なぜデフォルトのテンプレートがこれを自動的に含まないのかは私を超えています。
CoatedMoose 2017

4

より良い簡単な方法があります!

私は個人的に、この問題を解決するためにDNSサブドメインを使用することを好みます。私のCDNがsdf73n7ssa.cloudfront.netではなくcdn.myawesomeapp.comの背後にある場合、ブラウザーはフリークアウトせず、クロスドメインセキュリティの問題としてそれらをブロックしません。

サブドメインをAWS Cloudfrontドメインにポイントするには、AWS Cloudfrontコントロールパネルに移動し、Cloudfrontディストリビューションを選択して、CDNサブドメインを[Alternate Domain Names(CNAMEs)]フィールドに入力します。cdn.myawesomeapp.comのような何かが行います。

これで、DNSプロバイダー(AWS Route 53など)にアクセスして、sdf73n7ssa.cloudfront.netを指すcdn.myawesomeapp.comのCNAMEを作成できます。

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


これはSSLを破壊するか、SSLを使用するには多くの費用がかかるため、多くの人はSSLを使用しません。
不正行為者

4

この構成でうまくいきました。オブジェクトの一覧表示、取得、更新、削除ができます。

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

:私はCORSのために、このページではlocalhost、ジャストの外観からテストしていたとして、あなたは、変更のドメインに必要docs.aws.amazon.com/AWSJavaScriptSDK/guide/...
シャヒード

1
<ifModule mod_headers.c>

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

</ifModule>

シンプルなソリューション


共有してくれてありがとう!私と同じように、このヘッダーを追加するためのアイデア与えた「メタデータ」しながら、アップロードクラウドストレージへの静的な資産を。(ただし、1 particular domainまたはでのみ機能しますall domains
Vinay Vissh

0

Spring Bootアプリケーション(サーバー)を再起動すると、問題が解決しました。

CORSをS3で正しく設定しました。curlはoriginヘッダーで正しい応答を返していました。Safariはフォントを正しくフェッチしていました。CORSを受け入れたくないのはクロムだけでした。

行動を正確に引き起こした原因がわからない。If-modified-sinceと関係がある必要があります


0

これはフォントではなく画像に関係しているため、極端なケースである可能性がありますが、私の場合、別のケースで発生する可能性があります。これが誰かに役立つことを願ってここに置いておきます:

「私は彼らが言ったすべてを実行しましたが、それでも機能しません」というシナリオにいる場合、それはおそらくChromeとSafariのキャッシュ関連の問題です。サーバーに適切なCORS構成セットがあると仮定します。

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

Firefoxではすべて正常に機能しますが、ChromeとSafariでは機能しません。次のように、単純なタグとjs Image要素srcの両方からリモート画像パスにアクセスしている場合<img src="http://my.remote.server.com/images/cat.png">

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'

No 'Access-Control-Allow-Origin'ChromeとSafariでエラーが発生する場合があります。これは、最初の<img>キャッシュがブラウザのキャッシュをなんとか壊してしまい、後で同じコード(コード内のImage要素上)にアクセスしようとすると、壊れるだけだからです。これを回避するには、次のように、架空のGETパラメータを1つの.srcパスに追加して、ブラウザに強制的に画像を再リクエストさせ、キャッシュの使用を回避させます。

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

-1

はい、もちろん。Firefoxは、仕様がhttp://dev.w3.org/csswg/css3-fonts/#allowing-cross-origin-font-loadingで必要とするのと同じように、フォントのCORSをサポートしています


迅速な対応ありがとうございます、Boris Zbarsky。S3 CORS設定の構成例をいくつか示すことができますか?
VKen

私はS3の設定を調べたことはありません... HTTPレベルで何を送信するかについては、それが問題なければ、フォントファイルのHTTP応答で「Access-Control-Allow-Origin:*」を送信するだけです。うまくいくはずです。
Boris Zbarsky 2012

おかげで、私はS3 CORS構成でその設定を行う方法を正確に見つけようとしています。
VKen 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.