Amazon S3 CORS (совместное использование ресурсов для разных источников) и загрузка междоменных шрифтов Firefox
Проблема с Firefox не связана с загрузкой шрифта из разных источников, чем текущая веб-страница. Обычно проблема возникает, когда шрифты подаются на CDN.
В других вопросах были подняты различные решения:
CSS @font-face не работает с Firefox, но работает с Chrome и IE
С введением Amazon S3 CORS существует ли решение, использующее CORS для решения проблемы загрузки шрифтов в Firefox?
edit: Было бы здорово увидеть образец конфигурации S3 CORS.
edit2: Я нашел рабочее решение, не понимая, что он сделал. Если кто-то может предоставить более подробные объяснения о конфигурациях и фоновой магии, которые происходят при интерпретации Амазонки в конфиге, будет очень признателен, как и в случае с nzifnab, который выставил за это щедрость.
Ответы
Ответ 1
Обновление 10 сентября 2014 года:
Вам больше не нужно предпринимать какие-либо действия, описанные ниже, так как Cloudfront теперь правильно поддерживает CORS. См. http://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/ и этот ответ для получения дополнительной информации: fooobar.com/questions/46082/...
ОК, я наконец-то начал работать со шрифтами, используя приведенную ниже конфигурацию с небольшим изменением примеров в документации.
Мои шрифты размещены на S3, но выходят на облачный фронт.
Я не уверен, почему это работает, я думаю, вероятно, что <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>
редактировать:
Некоторые разработчики сталкиваются с проблемами кэширования Cloudfront заголовка Access-Control-Allow-Origin
. Эта проблема была решена сотрудниками AWS по ссылке (https://forums.aws.amazon.com/thread.jspa?threadID=114646) ниже, прокомментированной @Jeff-Atwood.
Из связанной ветки рекомендуется в качестве обходного пути использовать строку запроса для разграничения вызовов из разных доменов. Я приведу сокращенный пример здесь.
Использование 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-Origin
возвратил другие значения, которые прошли кеширование Cloudfront.
Ответ 2
После некоторой настройки я, кажется, заставил это работать без взлома строки запроса. Больше информации здесь: http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorS3Origin.html#RequestS3-cors
Я собираюсь пройти всю мою настройку, чтобы было легко увидеть, что я сделал, надеюсь, это поможет другим.
Исходная информация:
Я использую приложение Rails, у которого есть гем asset_sync для размещения ресурсов на S3. Это включает в себя шрифты.
В консоли S3 я нажал на свой контейнер, свойства и "редактировать конфигурацию коров", здесь: ![CORS config button]()
Внутри текстовой области у меня есть что-то вроде:
<?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) я создал дистрибутив, добавил Origin, который указывал на мою корзину S3
![adding an origin]()
Затем добавлено поведение для пути по умолчанию, указывающего на исходную точку S3, которую я установил. Я также нажал на заголовки белого списка и добавил Origin
:
![adding a behavior and whitelist headers]()
Что происходит сейчас, так это то, что я считаю правильным:
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 секунд, но то же самое работало и с хитами)
3) Хит облачного фронта с другим источником (но разрешенным в CORS для корзины S3) - 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==
Обратите внимание, что домен успешно изменился без взлома строки запроса.
Когда я изменяю заголовок источника, кажется, что всегда есть X-Cache: Miss from cloudfront
в первом запросе, а затем я получаю ожидаемый X-Cache: Hit from cloudfront
Постскриптум Стоит отметить, что при выполнении curl -I (заглавная I) НЕ будет отображаться заголовок Access-Control-Allow-Origin, так как это только HEAD, я делаю -I, чтобы сделать его GET и прокрутить вверх.
Ответ 3
Мои шрифты были правильно поданы до последнего нажатия на Heroku... Я не знаю, почему, но шаблон в CORS позволил происходить, перестало работать. Я добавил все мои prepro и pro домены в политику CORS в настройке bucket, поэтому теперь он выглядит так:
<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: добавьте также http://localhost:PORT
Ответ 4
Ну, в документации указано, что вы можете придерживать конфигурацию как "корсет cors в вашем ковше". Я воспринял это как означающий, что я создам файл под названием "корс" в корне моего ковша с конфигурацией, но это не сработает. В итоге мне пришлось войти в административную область Amazon S3 и добавить конфигурацию в диалоговом окне properties
моего ковша.
S3 может использовать некоторую лучшую документацию...
Ответ 5
В моем случае я не определил пространство имен и версию XML в конфигурации CORS. Определение тех, кто работал.
Измененный
<CORSConfiguration>
к
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
Ответ 6
В 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 хорошо работает для файлов Javascript и CSS, но не работает для файлов шрифтов.
Вы должны указать домен, чтобы разрешить CORS, используя шаблон, выраженный в ответе @VKen: fooobar.com/questions/46082/...
Итак, используйте это:
<?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), и он будет работать.
Ответ 7
Есть лучший и простой способ!
Я лично предпочитаю использовать свои поддомены DNS для решения этой проблемы. Если мой CDN находится за cdn.myawesomeapp.com, а не sdf73n7ssa.cloudfront.net, тогда браузеры не будут freakout и блокировать их как проблемы безопасности между доменами.
Чтобы указать ваш поддомен на ваш домен облачного облака AWS, перейдите в панель управления AWS Cloudfront, выберите свой дистрибутив Cloudfront и введите субдомен CDN в поле Alternate Domain Names (CNAMEs). Будет что-то вроде cdn.myawesomeapp.com.
Теперь вы можете обратиться к поставщику DNS (например, AWS Route 53) и создать CNAME для cdn.myawesomeapp.com, указав на sdf73n7ssa.cloudfront.net.
http://blog.cloud66.com/cross-origin-resource-sharing-cors-blocked-for-cloudfront-in-rails/
Ответ 8
Эта конфигурация работала для меня. Я могу перечислить объект, получить, обновить и удалить.
<?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>
Ответ 9
<ifModule mod_headers.c>
Header set Access-Control-Allow-Origin: http://domainurl.com
</ifModule>
Простое решение
Ответ 10
Перезагрузка моего приложения загрузки (сервера) spring решила проблему для меня.
Я правильно настроил CORS на S3.
Curl дал правильный ответ с заголовком источника.
Safari правильно отображает шрифт.
Это был только хром, который не хотел принимать CORS.
Не уверен, что именно вызвало поведение.
Должно быть, что-то делать с if-modified-since
Ответ 11
Это связано не со шрифтами, а с изображениями, это может быть крайний случай, но, как это случилось со мной, это может произойти и с другим. Я оставлю это здесь, надеясь, что это кому-нибудь поможет:
Если вы находитесь в сценарии "Я сделал все, что они сказали, но он все равно не сработает", вероятно, это проблема с кешем в 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 - нет.
Если вы обращаетесь к пути к удаленному изображению из и простого тега <img src="http://my.remote.server.com/images/cat.png">
, и из ssc элемента изображения js, например, следующим образом:
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 к одному пути .src, чтобы заставить браузер повторно запрашивать изображение и избегать использования кэша, например:
<img src="http://my.remote.server.com/images/cat.png?nocache=true"></img>
Ответ 12
Да, конечно. Firefox поддерживает CORS для шрифтов, точно так же, как спецификация требует http://dev.w3.org/csswg/css3-fonts/#allowing-cross-origin-font-loading
Ответ 13
У меня была такая же проблема. Мне не нужно было добавлять CNAME в мой CDD, чтобы избежать проблем с перекрестными доменами... Мне просто нужно было сделать следующее:
Перейдите в свойства вашего Bucket → Разрешения → Добавить дополнительные разрешения → Грантополучатель: все и проверьте опцию "список".
Это графический пример. http://i.stack.imgur.com/KOEwy.png
Надеюсь, что это будет полезно для кого-то.