AWS: Как я могу разрешить несколько доменов в конфигурации S3 CORS?
У меня возникла проблема на многих моих сайтах, которые используют S3 как источник для Cloudfront. Однако у меня возникают проблемы с разрешением нескольких доменов (вместо глобального *
позволил).
Я следовал за документацией здесь (первый конфиг). И нашел несколько других случайных ответов SO или форума тут и там (второй конфиг)
Любая помощь приветствуется.
Я установил правила 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>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>https://staging.example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://example.dev</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
А ТАКЖЕ
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://example.com</AllowedOrigin>
<AllowedOrigin>http://example.com</AllowedOrigin>
<AllowedOrigin>https://staging.example.com</AllowedOrigin>
<AllowedOrigin>http://example.dev</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Я получаю ошибку происхождения шрифта на всех сайтах, кроме https://example.com
:
Шрифт из источника ' http: // CLOUDFRONTURL ' заблокирован для загрузки политикой общего доступа к ресурсам разных источников: в запрошенном ресурсе отсутствует заголовок "Access-Control-Allow-Origin". Поэтому происхождение " http://example.dev/ " не разрешено.
А ТАКЖЕ
Шрифт из источника ' http: // CLOUDFRONTURL ' заблокирован для загрузки политикой общего доступа к ресурсам разных источников: заголовок "Access-Control-Allow-Origin" имеет значение " https://example.com/ ", которое не равно к поставляемому источнику. Поэтому происхождение " http://example.dev/ " не разрешено.
2 ответа
CloudFront кэширует объекты на основе всех заголовков запросов, которые он пересылал из браузера на исходный сервер, а не только по пути.
Чтобы ответ был отправлен из кэша, он должен быть возвращен в ответ на предыдущий запрос, который содержал точно такие же заголовки запроса.
Это связано с тем, что, по крайней мере, в принципе, разные заголовки могут вызывать различное поведение сервера, а хорошо функционирующий кеш не может предполагать иное.
Чтобы повысить кешируемость объектов, не ставя под угрозу его способность обслуживать правильные ответы (т. Е. Идентичный ответ, который сервер отправителя возвратил бы для данного запроса), CloudFront удаляет почти заголовки запроса перед отправкой запроса в источник и использует Урезанная версия запроса при выполнении поиска в кэше.
Когда исходный сервер является источником "Пользовательский" (т. Е. Не S3), вы можете выбрать, какие заголовки пересылать на исходный сервер.
Но когда исходным сервером является S3, у вас все еще есть выбор, но есть только три, которые могут быть переадресованы... и все они связаны с CORS.
[С источником S3] вы можете настроить CloudFront для пересылки и кэширования ваших объектов только на основе трех заголовков:
Access-Control-Request-Headers
,Access-Control-Request-Method
, а такжеOrigin
, Пересылка этих заголовков позволяет CloudFront распространять контент для веб-сайтов, для которых разрешено совместное использование ресурсов между источниками (CORS). Вы не можете настроить CloudFront для пересылки пользовательских заголовков в Amazon S3.http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html
Если Origin:
заголовок, по крайней мере, не перенаправляется, тогда S3 не сможет на него отреагировать. Включение пересылки этого заголовка означает, что S3 не только увидит его и, возможно, изменит его ответ из-за конфигурации CORS в корзине, но также и что каждый вариант Origin:
- для одного и того же объекта - приведет к тому, что S3 вернет другой (и правильный) ответ и будет кеширован для будущих запросов на совпадение CloudFront.
Пользовательские заголовки не могут быть перенаправлены в S3 с помощью CloudFront, потому что это бесполезно - поскольку S3 хранит статическое содержимое, ответы не будут меняться для других заголовков, поэтому их пересылка будет бессмысленной и снизит частоту обращений в кэш, а многие (предположительно) различные ответы кэшируются, но обслуживаются только в ответ на запросы, сопровождаемые одинаковыми заголовками.
Предыстория: ваша установка
- Допустим, у вас есть домен A (например) и домен B (например).
- Ваш CDN находится в
cdn.mydomain.com
который находится на CloudFront и указывает на частную корзину S3. - Файлы (например, требующие CORS для каждого MDN) доступны, когда вы запрашиваете их через
https://cdn.mydomain.com/fonts/myfont.woff
. (См. Мой ответ здесь о том, как его настроить до этого момента.)
Требования (только для этого вопроса)
- Вы хотите, чтобы файл был доступен на
cdn.mydomain.com/fonts/myfont.woff
только когда запрашивающая страница (т.е. заголовок) либоdev.mydomain.com
или жеwww.mydomain.com
. - Вы НЕ хотите, чтобы файл был доступен, когда
junk-cheap.com
загружает ваш файл шрифта на эту страницу (через URL вашего CDN), чтобы сэкономить на собственной полосе пропускания / стоимости хостинга; не говоря уже о фишинге и подобных рисках!
Проблема
По умолчанию CloudFront кеширует ответ на любой входящий запрос. В этом весь смысл CDN.
Однако в первый раз (после признания недействительным) запрос поступает из любого из двух доменов для определенного файла (скажем,
/fonts/myfont.woff
) CloudFront кэширует ответ для этого файла как
{ "/fonts/myfont.woff": "<this response object with headers>"}
. Таким образом, кеш-ключ по умолчанию - это почти только путь.
Теперь, когда запрос из домена B приходит для того же файла, «разрешено домен» из кэшированного отклика объекта для домена А, и это несоответствие приводит к ошибке CORS.
Решение
Одним из простых решений было бы указать CloudFront включить ключ кеша. Итак, в приведенном выше примере кеш будет иметь вид
{ ["/fonts/myfont.woff", "Origin: www.mydomain.com"]: <response for www.mydomain.com only>, ... }
.
Вы можете добиться этого, создав новую политику кеширования, которая принимает
Origin
заголовок:
а затем настройте его на свое поведение.
Теперь сделайте раздачу недействительной и попробуйте снова! Он должен работать. :)
Удачи!