关于css:Amazon S3 CORS(跨源资源共享)和Firefox跨域字体加载

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。

我不知道为什么它会起作用,我猜可能需要GETContent-*

如果任何一个精通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缓存Access-Control-Allow-Origin头的问题。此问题已由AWS工作人员在链接(https://forums.aws.amazon.com/thread.jspa)中解决。threadid=114646),由@jeff atwood评论。

从链接线程来看,作为解决方法,建议使用查询字符串来区分来自不同域的调用。我将在这里重现这个简短的示例。

使用curl检查响应头:

域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

您会注意到Access-Control-Allow-Origin返回了不同的值,这些值已经超过了CloudFront缓存。


在做了一些调整之后,我似乎可以不使用查询字符串hack来工作。更多信息请访问:http://docs.aws.amazon.com/amazoncloudfront/latest/developerguide/requestandresponsebehaviors3origin.html requests3 cors

我将完成整个设置,以便很容易看到我所做的,希望这能帮助其他人。

背景信息:我正在使用一个有资产同步宝石的Rails应用程序将资产放到S3上。这包括字体。

在S3控制台中,我单击了我的bucket、属性和"编辑CORS配置",这里是:CORS config button

在文本区域内,我有如下内容:

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设置。我还点击了白名单的标题并添加了Origin:氧化镁

现在发生的事情是,我认为是正确的:

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上允许使用的源攻击)-Access-Control-Allow-Origin不缓存!小精灵!

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

请注意,域已成功更改,没有查询字符串黑客。

当我更改原始头段时,第一个请求似乎总是有一个X-Cache: Miss from cloudfront,然后我得到预期的X-Cache: Hit from cloudfront

另外,值得注意的是,当执行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>

更新:添加你的http://localhost:PORT


好吧,文档说明您可以将配置坚持为"您的bucket中的CORS子资源"。我认为这意味着我将在bucket的根目录创建一个名为"CORS"的文件,但这不起作用。最后,我必须登录到AmazonS3管理区域,并在我的bucket的properties对话框中添加配置。

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

希望这对某人有用。