Amazon S3 CORS (Cross-Origin Resource Sharing) and Firefox cross-domain font loading
Firefox长期以来一直存在着一个问题,它没有从不同的源网站加载字体。通常,当字体提供给cdn时,就会出现这个问题。
在其他问题中提出了各种解决方案:
CSS@Font Face不使用Firefox,但使用Chrome和IE
随着AmazonS3CORS的引入,有没有一个使用CORS解决火狐字体加载问题的解决方案?
编辑:很高兴看到S3CORS配置的示例。
伊迪丝2:我发现了一个有效的解决方案,但实际上并不了解它的作用。如果有人能提供关于配置和背景魔法的更详细的解释,在亚马逊对配置的解释上发生的,这将是非常感谢,与Nzifnab谁提出了赏金。
2014年9月10日更新:
由于CloudFront现在正确地支持CORS,您不需要再进行下面的任何查询字符串黑客操作。有关更多信息,请参阅http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/和此答案:https://stackoverflow.com/a/25305915/308315
好的,我最终使用下面的配置让字体工作,并对文档中的示例进行了一些调整。
我的字体托管在S3上,但前面是CloudFront。
我不知道为什么它会起作用,我猜可能需要
如果任何一个精通AmazonS3CORS配置的人都能对此有所启发,那将是非常感谢的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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> |
编辑:
一些开发人员面临着CloudFront缓存
从链接线程来看,作为解决方法,建议使用查询字符串来区分来自不同域的调用。我将在这里重现这个简短的示例。
使用
域A:a.domain.com
1 | curl -i -H"Origin: https://a.domain.com" http://hashhashhash.cloudfront.net/font.woff?https_a.domain.com |
号
来自域A的响应头:
1 2 3 4 5 | 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
1 | curl -i -H"Origin: http://b.domain.com" http://hashhashhash.cloudfront.net/font.woff?http_b.domain.com |
。
来自域B的响应头:
1 2 3 4 5 | 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 |
您会注意到
在做了一些调整之后,我似乎可以不使用查询字符串hack来工作。更多信息请访问:http://docs.aws.amazon.com/amazoncloudfront/latest/developerguide/requestandresponsebehaviors3origin.html requests3 cors
我将完成整个设置,以便很容易看到我所做的,希望这能帮助其他人。
背景信息:我正在使用一个有资产同步宝石的Rails应用程序将资产放到S3上。这包括字体。
在S3控制台中,我单击了我的bucket、属性和"编辑CORS配置",这里是:。
在文本区域内,我有如下内容:
1 2 3 4 5 6 7 8 9 | <?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 bucket的源站。氧化镁
然后添加默认路径的行为,以指向基于S3的原点i设置。我还点击了白名单的标题并添加了
现在发生的事情是,我认为是正确的:
1)检查S3头设置是否正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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与收割台的工作情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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== |
(注意,上面是CloudFront的一个失误,因为这些文件被缓存了180秒,但命中率也是如此)
3)使用不同的源攻击CloudFront(但S3 bucket的CORS上允许使用的源攻击)-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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== |
。
请注意,域已成功更改,没有查询字符串黑客。
当我更改原始头段时,第一个请求似乎总是有一个
另外,值得注意的是,当执行curl-i(大写I)时,不会显示访问控制allow origin headers,因为它只是一个head,我会-i使其成为get并向上滚动。
在最后一次推到Heroku之前,我的字体都是正确的。我不知道为什么,但是CORS中的通配符允许origin停止工作。我在bucket设置中将所有的prer和pro域添加到cors策略中,所以现在看起来是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 | <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> |
更新:添加你的
好吧,文档说明您可以将配置坚持为"您的bucket中的CORS子资源"。我认为这意味着我将在bucket的根目录创建一个名为"CORS"的文件,但这不起作用。最后,我必须登录到AmazonS3管理区域,并在我的bucket的
S3可以使用一些更好的文档…
在我的例子中,我没有在CORS配置中定义XML名称空间和版本。定义那些有效的。
改变
1 | <CORSConfiguration> |
。
到
1 2 | <?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> |
。
在Amazon S3 CORS配置(S3 bucket/permissions/CORS)中,如果使用此配置:
1 2 3 4 5 6 7 8 | <?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 answer:https://stackoverflow.com/a/25305915/618464中表示的模式的CORS
所以,使用这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?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),它将工作。
这个配置对我有效。我可以列出对象、检索、更新和删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?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> |
。
有更好更简单的方法!
我个人更喜欢使用我的DNS子域来解决这个问题。如果我的cdn落后于cdn.myawsomeapp.com而不是sdf73n7ssa.cloudfront.net,那么浏览器不会因为跨域安全问题而惊慌失措并将其阻止。
要将子域指向您的AWS CloudFront域,请转到AWS CloudFront控制面板,选择您的CloudFront分发版,并将您的cdn子域输入到备用域名(cnames)字段中。像cdn.myawesomeapp.com这样的网站可以做到。
现在,您可以转到您的DNS提供商(如AWS Route 53)并为cdn.myawsomeapp.com创建一个指向sdf73n7ssa.cloudfront.net的cname。
http://blog.cloud66.com/cross-origin-resource-sharing-cors-blocked-for-cloudfront-in-rails/
1 2 3 4 5 | <ifModule mod_headers.c> Header set Access-Control-Allow-Origin: http://domainurl.com </ifModule> |
。
简单解决方案
重新启动我的SpringBoot应用程序(服务器)为我解决了这个问题。
我在S3上正确配置了CORS。curl对origin header给出了正确的响应。Safari正在正确获取字体。只有铬合金不愿意接受这种胸衣。
不知道是什么导致了这种行为。如果修改的话一定是有关系的,因为
是的,当然。firefox支持字体CORS,就像规范在http://dev.w3.org/csswg/css3 fonts/上要求的那样,允许跨源字体加载。
我也遇到过同样的问题。我不需要在我的CDD中添加CNAME来避免跨域问题…我只需要做以下的事情:
转到您的bucket属性->权限->添加更多权限->被授予者:所有人并选中"列表"选项。
这是一个图形示例。http://i.stack.imgur.com/koewy.png
希望这对某人有用。