CSS Amazon S3 CORS (Cross-Origin Resource Sharing) 和 Firefox 跨域字体加载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12229844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading
提问by VKen
There has been a long standing issue with Firefox not loading font from different origin than the current webpage. Usually, the issue arise when the fonts are served on CDNs.
Firefox 无法加载来自与当前网页不同来源的字体,这是一个长期存在的问题。通常,在 CDN 上提供字体时会出现问题。
Various solutions has been raised in other questions:
在其他问题中提出了各种解决方案:
CSS @font-face not working with Firefox, but working with Chrome and IE
CSS @font-face 不适用于 Firefox,但适用于 Chrome 和 IE
With the introduction of Amazon S3 CORS, is there a solution using CORS to address the font loading issue in Firefox?
随着 Amazon S3 CORS 的引入,是否有使用 CORS 解决 Firefox 中字体加载问题的解决方案?
edit: It would be great to see a sample of the S3 CORS configuration.
编辑:很高兴看到 S3 CORS 配置的示例。
edit2: I have found a working solution without actually understanding what it did. If anyone could provide more detailed explanations about the configs and the background magic that happens on Amazon's interpretation of the config, it will be greatly appreciated, as with nzifnab who put up a bounty for it.
编辑 2:我找到了一个有效的解决方案,但实际上并没有真正理解它的作用。如果有人可以提供有关配置的更详细的解释以及亚马逊对配置的解释所发生的背景魔法,我们将不胜感激,就像 nzifnab 为它提供赏金一样。
回答by VKen
Update September 10, 2014:
2014 年 9 月 10 日更新:
You shouldn't need to do any of the query string hacks below anymore since Cloudfront properly supports CORS now. See http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/and this answer for more info: https://stackoverflow.com/a/25305915/308315
由于 Cloudfront 现在正确支持 CORS,因此您不需要再执行下面的任何查询字符串技巧了。有关更多信息,请参阅http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/和此答案:https: //stackoverflow.com/a/25305915/308315
OK, I finally got the fonts working using the config below with a little tweak from examples in the documentation.
好的,我终于使用下面的配置使字体工作了,并从文档中的示例中稍作调整。
My fonts are hosted on S3, but fronted by cloudfront.
我的字体托管在 S3 上,但由 cloudfront 托管。
I'm not sure why it works, my guess is probably that the <AllowedMethod>
GET
and <AllowedHeader>
Content-*
is needed.
我不确定它为什么会起作用,我的猜测可能是<AllowedMethod>
GET
和<AllowedHeader>
Content-*
是需要的。
If anyone proficient with Amazon S3 CORS config can shed some lights on this, it'll be greatly appreciated.
如果任何精通 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>
edit:
编辑:
Some developers are facing issues of Cloudfront caching the Access-Control-Allow-Origin
header. This issue has been addressed by the AWS staff in the link (https://forums.aws.amazon.com/thread.jspa?threadID=114646) below, commented by @Jeff-Atwood.
一些开发人员面临 Cloudfront 缓存Access-Control-Allow-Origin
标头的问题。此问题已由 AWS 工作人员在下面的链接 ( https://forums.aws.amazon.com/thread.jspa?threadID=114646) 中解决,@Jeff-Atwood 对此进行了评论。
From the linked thread, it is advised, as a workaround, to use a Query Stringfor differentiating between calls from different domains. I'll reproduce the shortened example here.
从链接的线程中,作为一种解决方法,建议使用查询字符串来区分来自不同域的调用。我将在此处重现缩短的示例。
Using curl
to check response headers:
使用curl
检查响应头:
Domain A: a.domain.com
域 A:a.domain.com
curl -i -H "Origin: https://a.domain.com" http://hashhashhash.cloudfront.net/font.woff?https_a.domain.com
Response headers from Domain A:
来自域 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
Domain B: b.domain.com
域 B:b.domain.com
curl -i -H "Origin: http://b.domain.com" http://hashhashhash.cloudfront.net/font.woff?http_b.domain.com
Response headers from Domain B:
来自域 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
You will notice the Access-Control-Allow-Origin
has returned different values, which got past the Cloudfront caching.
您会注意到Access-Control-Allow-Origin
已返回不同的值,这些值已通过 Cloudfront 缓存。
回答by Eamonn Gahan
After some tweaking I seem to have got this to work without the query string hack. More info here: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors
经过一些调整后,我似乎可以在没有查询字符串黑客的情况下使用它。更多信息:http: //docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors
I'm going to go through my entire setup so that it's easy to see what I've done, hopefully this helps others.
我将完成我的整个设置,以便很容易看到我所做的一切,希望这对其他人有所帮助。
Background Information: I'm using a Rails app that has the asset_sync gem to put assets onto S3. This includes fonts.
背景信息:我正在使用具有 asset_sync gem 的 Rails 应用程序将资产放到 S3 上。这包括字体。
Within S3 console, I clicked on my bucket, properties and 'edit cors configuration', here:
在 S3 控制台中,我在此处单击了我的存储桶、属性和“编辑 cors 配置”:
Inside the textarea I have something like:
在 textarea 里面,我有类似的东西:
<?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>
Then within Cloudfront panel (https://console.aws.amazon.com/cloudfront/home) I created a distribution, added an Origin that pointed to my S3 bucket
然后在 Cloudfront 面板 ( https://console.aws.amazon.com/cloudfront/home) 中,我创建了一个发行版,添加了一个指向我的 S3 存储桶的 Origin
Then added a behavior for a default path to point to the S3 based origin I setup. What I also did was click on Whitelist headers and added Origin
:
然后为默认路径添加了一个行为以指向我设置的基于 S3 的原点。我还做的是点击白名单标题并添加Origin
:
What happens now is the following, which I believe is right:
现在发生的事情如下,我认为这是正确的:
1) Check that S3 headers are being set correctly
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) Check Cloudfront works with the headers
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==
(Note the above was a miss from cloudfront because these files are cached for 180 seconds, but the same was working on hits)
(请注意,上述内容来自 cloudfront,因为这些文件缓存了 180 秒,但同样适用于命中)
3) Hit cloudfront with a different origin (but one that is allowed on CORS for the S3 bucket) - the Access-Control-Allow-Origin
is not cached! yay!
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==
Note above that the domain has successfully changed without a query string hack.
请注意,在没有查询字符串破解的情况下,域已成功更改。
When I change the Origin header, there seems to always be a X-Cache: Miss from cloudfront
on the first request then afterwards I get the expected X-Cache: Hit from cloudfront
当我更改 Origin 标头时,X-Cache: Miss from cloudfront
第一个请求似乎总是有一个,然后我得到了预期的X-Cache: Hit from cloudfront
P.S. It is worth noting that when doing curl -I (capital I) will NOT show the Access-Control-Allow-Origin headers as it only a HEAD, I do -i to make it a GET and scroll up.
PS 值得注意的是,在执行 curl -I(大写 I)时不会显示 Access-Control-Allow-Origin 标头,因为它只是一个 HEAD,我执行 -i 以使其成为 GET 并向上滚动。
回答by luigi7up
My fonts were served correctly until the last push to Heroku... I don't know why, but the wildcard in the CORS allowed origin stopped working. I added all of my prepro and prodomains to the CORS policy in the bucket setting so now it looks like this:
我的字体在最后一次推送到 Heroku 之前一直正确提供......我不知道为什么,但是 CORS 中的通配符允许 origin 停止工作。我将所有 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>
UPDATE: add your http://localhost:PORT
too
更新:添加您的http://localhost:PORT
太
回答by nzifnab
Well, the documentation states that you can stick the configuration as "the cors subresource in your bucket." I took this to mean I would create a file called "cors" at the root of my bucket with the configuration, but this would not work. In the end I had to login to the Amazon S3 administration area and add the configuration within the properties
dialog of my bucket.
好吧,文档指出您可以将配置粘贴为“存储桶中的 cors 子资源”。我认为这意味着我将使用配置在存储桶的根目录创建一个名为“cors”的文件,但这不起作用。最后,我必须登录 Amazon S3 管理区域并在properties
存储桶的对话框中添加配置。
S3 could use some better documentation...
S3 可以使用一些更好的文档...
回答by educoutinho
In Amazon S3 CORS configuration(S3 Bucket / Permissions / CORS) if you use this:
在 Amazon S3 CORS 配置(S3 Bucket / Permissions / 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 works well for Javascript and CSS files, but It does not work for Font files.
CORS 适用于 Javascript 和 CSS 文件,但不适用于字体文件。
You have to specify the domain to allow CORS using the pattern expressed in the @VKen answer: https://stackoverflow.com/a/25305915/618464
您必须使用@VKen 答案中表达的模式指定域以允许 CORS:https://stackoverflow.com/a/25305915/618464
So, use this:
所以,使用这个:
<?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>
Remember to replace "mydomain.com" for your domain.
请记住为您的域替换“mydomain.com”。
After this, invalidate the CloudFront cache(CloudFront / Invalidations / Create Invalidation) and It will work.
在此之后,使 CloudFront 缓存无效(CloudFront / Invalidations / Create Invalidation),它将起作用。
回答by Gaurav Toshniwal
In my case, I hadn't defined XML namespace and version in CORS configuration. Defining those worked.
就我而言,我没有在 CORS 配置中定义 XML 命名空间和版本。定义那些工作。
Changed
改变了
<CORSConfiguration>
to
到
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
回答by msroot
There is a better and easier way!
有更好更简单的方法!
I personally prefer using my DNS subdomains to solve this problem. If my CDN is behind cdn.myawesomeapp.com instead of sdf73n7ssa.cloudfront.net then browsers are not going to freakout and block them as cross domain security problems.
我个人更喜欢使用我的 DNS 子域来解决这个问题。如果我的 CDN 在 cdn.myawesomeapp.com 而不是 sdf73n7ssa.cloudfront.net 后面,那么浏览器就不会因为跨域安全问题而惊慌失措并阻止它们。
To point your subdomain to your AWS Cloudfront domain go to AWS Cloudfront control panel, select your Cloudfront distribution and enter your CDN subdomain into the Alternate Domain Names (CNAMEs) field. Something like cdn.myawesomeapp.com will do.
要将您的子域指向您的 AWS Cloudfront 域,请转到 AWS Cloudfront 控制面板,选择您的 Cloudfront 分配并将您的 CDN 子域输入到备用域名 (CNAME) 字段中。像 cdn.myawesomeapp.com 这样的东西就可以了。
Now you can go to your DNS provider (like AWS Route 53) and create a CNAME for cdn.myawesomeapp.com pointing to sdf73n7ssa.cloudfront.net.
现在,您可以转到您的 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/
http://blog.cloud66.com/cross-origin-resource-sharing-cors-blocked-for-cloudfront-in-rails/
回答by Shahid
This configuration worked for me. I can list object, retrieve, update and delete.
这个配置对我有用。我可以列出对象、检索、更新和删除。
<?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>
回答by O-mkar
<ifModule mod_headers.c>
Header set Access-Control-Allow-Origin: http://domainurl.com
</ifModule>
Simple Solution
简单的解决方案
回答by Sujit Kamthe
Restarting my spring boot application (server) solved the problem for me.
重新启动我的 Spring Boot 应用程序(服务器)为我解决了这个问题。
I had configured CORS correctly on S3. The curl was giving the correct response with origin header. Safari was fetching the font correctly. It was only the chrome who was not willing to accept the CORS.
我在 S3 上正确配置了 CORS。curl 使用原始标头给出了正确的响应。Safari 正在正确获取字体。只有铬不愿意接受 CORS。
Not sure what exactly caused the behaviour. Must be something to do with If-modified-since
不确定究竟是什么导致了这种行为。必须与 If-modified-since 有关