Проблемы с CORS с Amazon S3 на последних версиях Chomium и Google Canary
На нашем сайте возникают проблемы с загрузкой ресурсов CSS и JS на ведро Amazon S3 с самой последней версией Chromium (версия 33.0.1722.0 - 237596) и Chrome Canary.
Он хорошо работает с любым из других браузеров, включая текущий Chrome (31.0.1650.57).
Ошибка:
Script from origin 'https://mybucket.s3.amazonaws.com' заблокирован от загрузки политикой совместного использования ресурсов Cross-Origin: No 'Access- Заголовок Control-Allow-Origin присутствует на запрошенном ресурсе. Происхождение https://app.example.com ', следовательно, не допускается.
Наша конфигурация 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>300000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Это ошибка с Chromium?
Что-то изменилось в последней спецификации CORS?
Ответы
Ответ 1
Amazon выпустила исправление для этого несколько месяцев назад. Мы видели ошибки в текущих версиях Chrome и Safari (не проверяли Firefox). Для тех, кто все еще сталкивается с этой проблемой, попробуйте следующую конфигурацию:
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>
</CORSConfiguration>
Настройки распространения CloudFront (вкладка "Поведение" ):
- Разрешенные методы HTTP: GET, HEAD, OPTIONS
- Форвардные заголовки: белый список
- Заголовки белых списков: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Мы размещаем css и статические файлы javascript через CloudFront с источником S3. Мы ссылаемся на наши файлы javascript через
<script crossorigin="anonymous" src="http://assets.domain.com/app.js">
.
ИЗМЕНИТЬ
Мы снова начали эту проблему с Safari 10.1.2. Оказывается, мы обращались к файлу Javascript двумя способами...
На странице A через <script crossorigin="anonymous" src="http://assets.domain.com/app.js">
.
На странице B через $.ajax()
(чтобы он был ленивым загружен).
Если вы перешли на страницу A → стр. B → стр. A, мы получили бы ошибку перекрестного происхождения. Мы выбрали ленивый подход к загрузке и решили нашу проблему (снова).
Ответ 2
По всей вероятности, вы столкнулись с очень известной проблемой с S3/CloudFront/CORS. Лучшее решение, которое я смог найти, - это приложение, которое проксирует между S3 и CloudFront, всегда добавляя соответствующие заголовки CORS к объектам по мере их возвращения.
S3 + CloudFront сломаны, когда дело доходит до обслуживания активов CORS для разных веб-браузеров. Проблема в два раза.
- Не все браузеры требуют CORS для веб-шрифтов и других статических активов. Если один из этих браузеров делает запрос, S3 не отправляет заголовки CORS, а CloudFront кэширует (бесполезный) ответ.
- CloudFront не поддерживает заголовок
Vary: Origin
, поэтому он имеет проблемы с использованием *
для значения AllowedOrigin
и будет кэшировать только первый из нескольких значений AllowedOrigin
.
В конце концов, эти две проблемы делают S3 + CloudFront неприемлемым решением для использования CORS с (быстрым) решением CDN - по крайней мере, из коробки. Пуленепробиваемым решением является создание простого приложения, которое проксирует запросы между S3 и CloudFront, всегда добавляя необходимые заголовки CORS, чтобы CloudFront всегда их кэшировал.
Запрос на "холодный" кеш
- ← Браузер запрашивает статический актив у CloudFront.
- ← CloudFront пропускает и запускает свой исходный сервер (приложение Proxy).
- ← Прокси-приложение передает запрос на S3.
- → S3 отвечает на прокси-приложение.
- → Приложение Proxy добавляет правильные заголовки CORS (независимо от того, отправил ли S3 их или нет). Приложение Proxy откликнется на CloudFront.
- → CloudFront кэширует результат и отвечает на браузер.
Запрос на "теплый" кеш
- ← Браузер запрашивает статический актив у CloudFront.
- → CloudFront обращается к браузеру.
Да, это широко известная проблема:
Я могу сказать, что наши команды S3 и CloudFront хорошо осведомлены о проблемах, обсуждаемых здесь. Записывая простое приложение, которое может выступать в качестве прокси между S3 и CloudFront, вы можете вручную ввести все правильные заголовки CORS до того, как CloudFront их кэширует.
Если вы всегда работаете в Firefox, то, вероятно, вы этого не заметите - CloudFront всегда будет кэшировать ваши ответы с поддержкой CORS. Если вы работаете в основном в Safari или Chrome, вы увидите это гораздо чаще, когда вы переключаетесь обратно в браузер, который требует этих заголовков (Firefox и IE). Кроме того, если у вас есть отдельные среды разработки/постановки/производства, вы чаще всего сталкиваетесь с проблемами с несколькими источниками.
Ответ 3
Хотелось перезвонить с альтернативной теорией на этот старый вопрос: у Chrome есть ошибка/ "функция", в которой присутствует, по крайней мере, с августа 2014 года, что приводит к сбою запроса перекрестного происхождения, если ресурс был сначала загружен через обычную выборку, по-видимому, потому, что Chrome кэширует заголовки ресурсов CORS-less, а затем отказывается предоставить кешированный ресурс запросу на перекрестный запрос.
Что еще хуже для нашего тестирования в сложном сценарии, оно даже не обязательно полностью согласуется между обновлениями (поскольку порядок загрузки ресурсов?) и другими браузерами, похоже, не разделяет поведения.
Это была забавная охота за ошибками! Похоже, что просто добавление crossorigin='anonymous'
к любым тегам, загружающим ресурс, заставляет Chrome вытаскивать заголовки CORS, исправляя последующие запросы с кросс-началом.