После долгого поиска и борьбы с этим я обнаружил страницу, на которой написано, что CarrierWave не поддерживает подписанные URL-адреса CloudFront.URL-адреса со знаком CloudFront отличаются от URL-адресов со знаком S3, что вызвало у меня некоторую путаницу.Как только я понял это, стало намного легче узнать, что делать.
Если вы настроите CarrierWave с config.fog_public = false
, тогда он автоматически начнет подписывать URL-адреса S3, но его нельзя будет настроить для работы сFog
и частный контент CloudFront в версии CarrierWave, которую я использую (1.0.0)
.Я даже пытался использовать камень carrierwave-aws
, и это тоже не помогло.
Итак, что произойдет, это то, что CarrierWave подпишет URL, а хост будет выглядеть примерно так:
https://my_bucket_name.s3-us-west-2.amazonaws.com/uploads/...?signature...
Это указывает непосредственно на корзину S3, но мне нужно было указать наCloudFront.Мне нужно, чтобы хост выглядел так:
https://s3.cloudfront_domain_name.com/uploads/...
И что произойдет, если я установлю config.asset_host
равным моему местоположению в CloudFront, если я получу это (с двойной косой чертой перед «загрузкой»):
https://s3.cloudfront_domain_name.com//uploads/...
Это также дало понять, что CarrierWave еще не была разработана для использования с CloudFront.Надеюсь, они это улучшат.Это был мой обходной путь.Это уродливо, но это сработало, чтобы выполнить то, что мне было нужно, без необходимости изменять сам CarrierWave, так как я надеюсь, что CarrierWave в какой-то момент добавит поддержку CloudFront.
- Сначала я выполнил поиск / замену регулярных выражениймой URL и удалил часть хоста S3 и поместил на мою часть хоста CloudFront.
cf_url = s3_url.gsub("my_bucket_name.s3-us-west-2.amazonaws.com", "s3.cloudfront_domain_name.com")
- Затем я сделал еще одно регулярное выражение поиска / замены, чтобы удалить подписанный URL-адрес S3 в конце строки:
non_signed_cf_url = cf_url.gsub(/\?.+/, '')
Это связано с тем, что подпись будет неверной, поскольку она использует API для S3 ине для CloudFront для подписи URL. - Теперь я сам переподписываю URL, используя
cloudfront-signer
gem: signed_cf_url = Aws::CF::Signer.sign_url(non_signed_cf_url, :expires => 1.day.from_now)
Есть несколько других вещей, о которых вам нужно знать при обслуживании личного контентав CloudFront:
- В настройках поведения кэша для шаблона пути (не обязательно используемого по умолчанию) установите для «Ограничить доступ для просмотра (использование подписанных URL-адресов или подписанных файлов cookie)» значение «Да»
- Установите для «Доверенных подписчиков» значение «self»
- Установите для «Пересылки и кэширования строк запроса» значение «Пересылать все, кэшировать на основе всех», если вы хотите использовать другие строки запроса, отличные от подписи CloudFront.в вашем URL, например
response-content-disposition
и response-content-type
(я смог заставить их работать успешно, но они должны быть правильно закодированы в url_). - В настройках источника CloudFront установите свой идентификатор доступаи установите для «Предоставить разрешения на чтение для корзины» значение «Да, обновить политику корзины»
- . В общих настройках распространения убедитесь, что «Состояние распространения» установлено как «Включено», и что вы добавили CNAME в «Альтернатива».ДоменИмена (CNAME) ", если вы его используете.
- Если вы используете CNAME, убедитесь, что ваш DNS правильно настроен для указания на него имени вашего дистрибутива CloudFront.
- Наконец, после того, как вы установитеКонфигурации будут долго ждать, пока AWS обновит дистрибутив, поэтому вы не увидите изменений сразу.Может показаться, что ваше приложение / веб-сайт все еще не работает, пока изменения не распространятся через CloudFront.Это может усложнить настройку, потому что, если вы ошиблись, вам придется долго ждать, прежде чем вы увидите, как ваши изменения вступят в силу, и вы можете быть не уверены, что произошло.Но с этими настройками я смог заставить его работать на меня.
- Вы также можете создать более одного шаблона пути кеширования, чтобы часть контента была закрытой и требовала подписанного URL-адреса CloudFront, а другая - нет.Например, я установил шаблон пути
*.mp4
, который требует подписи для всех файлов mp4, и поместил его выше поведения по умолчанию.И тогда у меня по умолчанию установлено поведение кэша, НЕ требующее подписанных URL-адресов, что позволяет всем другим файлам, таким как изображения, быть общедоступными через дистрибутив CloudFront.