Проблемы с 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, исправляя последующие запросы с кросс-началом.