Amazon S3 CORS (Cross-Origin Resource Sharing) 및 Firefox 도메인 간 글꼴로드


134

Firefox가 현재 웹 페이지와 다른 출처에서 글꼴을로드하지 않는 문제가 오랫동안있었습니다. 일반적으로이 문제는 글꼴이 CDN에서 제공 될 때 발생합니다.

다른 질문에서 다양한 솔루션이 제기되었습니다.

CSS @ font-face는 Firefox에서는 작동하지 않지만 Chrome 및 IE에서는 작동합니다.

Amazon S3 CORS가 도입되면서 CORS를 사용하여 Firefox의 글꼴로드 문제를 해결하는 솔루션이 있습니까?

편집 : S3 CORS 구성의 샘플을 보는 것이 좋습니다.

edit2 : 실제로 무엇을했는지 이해하지 않고 작동하는 솔루션을 찾았습니다. 아마존이 구성을 해석 할 때 발생하는 구성 및 배경 마법에 대해 더 자세한 설명을 제공 할 수 있다면, 현상금을 지불 한 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> GETand 일 것입니다 <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를?
ov

1
@ov 리소스를 사용하는 도메인을 명시 적으로 설정했기 때문에 문제가 발생하지 않습니다. 이전에 게시 한 링크를 읽었습니다. 도메인이 명시 적으로 언급되어야한다는 다른 스레드에 대한 일부 회신을 모호하게 기억했습니다. 따라서 일부 제한으로 인해 <AllowedOrigin> * </ AllowedOrigin>은 실제로 허용되지 않습니다. 답글을 찾을 수 없습니다. 다른 곳에서 읽은 블로그 게시물 일 수 있습니다. 희망이 도움이됩니다.
VKen

3
단일 CORSRule 요소 내에 여러 AllowedOrigin 요소를 가질 수 있으므로 해당 CORSRule을 단일 요소로 결합 할 수 있습니다. 다른 요소는 동일하기 때문입니다.
벤 헐

4
@dan S3 버킷이 CloudFront에서 제공되는 경우이 공식 Amazon 답변에 설명 된대로 도메인별로 글꼴 쿼리 문자열변경하는 것 같습니다. forums.aws.amazon.com/thread.jspa?threadID=114646
Jeff Atwood

2
이것은 매우 실망스러운 문제였습니다. 좋은 소식은 S3가 올바른 작업을 수행하는 것처럼 보이므로 적어도 CloudFront를 통해 웹 폰트 이외의 모든 것을 제공하고 S3에서 직접 글꼴 파일을 제공하는 것이 가능하다는 것입니다. 안타깝게도, 자산이 모두 Rails 자산 파이프 라인을 통해 제공되고 요청시 자산 URL을 조정할 수있는 편리한 방법이 없기 때문에 더 중요한 리팩토링이 없으면 애플리케이션에서 쿼리 스트링 핵이 실제로 실용적이지 않습니다. 자산이 사전 컴파일 될 때). CSS의 글꼴 URL은 이미 S3에 있습니다.
Zach Lipton

97

약간의 조정 후 쿼리 문자열 해킹없이 작동하는 것으로 보입니다. 자세한 정보는 여기 : http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors

나는 내가 한 일을 쉽게 볼 수 있도록 전체 설정을 살펴볼 것입니다.

배경 정보 : Asset_sync gem이있는 Rails 앱을 사용하여 자산을 S3에 넣습니다. 글꼴이 포함됩니다.

S3 콘솔에서 버킷, 속성 및 'edit cors configuration'을 클릭했습니다. 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 기반 원점 I 설정을 가리 키도록 기본 경로에 대한 동작을 추가했습니다. 또한 화이트리스트 헤더를 클릭하고 추가했습니다 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에서 허용되는 것)- 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

추신 : curl -I (자본 I)를 수행 할 때 HEAD만으로 Access-Control-Allow-Origin 헤더를 표시하지 않을 것입니다 .GET으로 만들고 위로 스크롤하기 위해 -i를 수행합니다.


다른 모든 사람들이하지 않았을 때 일했습니다. 시간을내어 자세한 내용을 게시 해 주셔서 감사합니다!
iwasrobbed

효과가있다!! 참고-이것을 테스트 할 때 거대한 http 응답 텍스트가 있습니다 ...이 컬 솔루션을 사용하기 위해 답변을 편집 할 것입니다 ... stackoverflow.com/questions/10060098/…
Michael Gorham

멋진 고마워요-다른 사람들을 위해 일하는 것을 보게되어 기쁩니다.
Eamonn Gahan

당신이 우리를 얼마나 도왔는지 말할 수 없습니다! +1
특별한 장소는 없습니다.

1
OriginCloudfront가 해당 헤더를 기반으로 객체를 캐시하고 서버 CORS 헤더를 사용자에게 다시 전달하도록 뷰어에서 고객 헤더를 추가하는 경우 +1
Sébastien Saunier

13

Heroku에 마지막으로 푸시 할 때까지 내 글꼴이 올바르게 제공되었습니다 ... 이유를 모르겠지만 CORS의 와일드 카드로 인해 원본이 작동하지 않았습니다. 버킷 설정에서 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 파일 에서는 잘 작동 하지만 Font files에서는 작동하지 않습니다 .

@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

기본 템플릿에 자동으로 포함되지 않는 이유는 무엇입니까?
CoatedMoose

4

더 쉽고 쉬운 방법이 있습니다!

개인적으로이 문제를 해결하기 위해 DNS 하위 도메인을 사용하는 것을 선호합니다. 내 CDN이 sdf73n7ssa.cloudfront.net 대신 cdn.myawesomeapp.com 뒤에 있으면 브라우저는 도메인 간 보안 문제로 기절하지 않으며 차단하지 않습니다.

하위 도메인을 AWS Cloudfront 도메인으로 지정하려면 AWS Cloudfront 제어판으로 이동하여 Cloudfront 배포를 선택하고 CDN 하위 도메인을 CNAME (대체 도메인 이름) 필드에 입력하십시오. 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과 관련하여 많은 비용이 들기 때문에 많은 사람들이 이것을하지 않습니다.
maletor 2019

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>

localhost에서 테스트 할 때 도메인을 변경해야합니다. CORS에 대한이 페이지를 참조하십시오. docs.aws.amazon.com/AWSJavaScriptSDK/guide/…
Shahid

1
<ifModule mod_headers.c>

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

</ifModule>

간단한 솔루션


공유해 주셔서 감사합니다! 정적 자산을 클라우드 스토리지에 업로드 하는 동안 이 헤더를 '메타 데이터' 로 추가하는 아이디어를 주셨습니다 . (하지만 그렇게 1 또는 작동합니다 )particular domainall domains
Vinay Vissh

0

스프링 부트 응용 프로그램 (서버)을 다시 시작하면 문제가 해결되었습니다.

S3에서 CORS를 올바르게 구성했습니다. 컬이 원점 헤더로 올바른 응답을 제공했습니다. 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>브라우저 캐시를 어지럽히고 나중에 코드 내 이미지 요소에서 동일한 이미지에 액세스하려고 할 때 발생하기 때문에 발생합니다 . 이를 피하기 위해 브라우저가 이미지를 다시 요청하도록하고 캐시를 사용하지 않도록 가상의 GET 매개 변수를 하나의 .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

감사합니다 .S3 CORS 구성을 사용하여 해당 설정을 수행하는 방법을 정확히 찾으려고합니다.
VKen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.