Content-Security-Policy¶
Если ваш магазин отправляет заголовок Content-Security-Policy (или его аналог в <meta http-equiv>), браузер блокирует
всё, что политика не разрешает. На этой странице перечислено, что именно нужно виджету Ziex Try-On. Страница описывает
виджет в том виде, в каком он выпущен сегодня (фаза 1); раздел Что изменится дальше говорит о
планах.
Если на вашей странице нет CSP, ничего из этого не нужно.
Что разрешить¶
| Директива | Что добавить | Зачем |
|---|---|---|
script-src |
https://api.ziex-tryon.com |
Виджет (tryon-embed.js) и лоадер (tryon-loader.js) отдаются с хоста API. |
connect-src |
https://api.ziex-tryon.com |
Все запросы виджета (отправка примерки, статус, список категорий, сохранённая копия результата) идут на хост API. |
img-src |
https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob: и ваши собственные хосты картинок |
media.ziex-tryon.com отдаёт картинки результатов; data: нужен для превью фото покупателя; blob: — для миниатюр и полноразмерного просмотра в «Моих образах». Картинки товара загружаются через <img>, поэтому хосты, которые их отдают (ваш магазин или его CDN), должны быть разрешены здесь. |
style-src |
'unsafe-inline' |
Виджет кладёт элемент <style> в собственный shadow root и использует несколько inline-атрибутов style. |
Замечания:
- Виджет не использует
frame-src,font-src,media-src,worker-srcиobject-src. - Картинки товара не запрашиваются через
connect-src. Виджет загружает их как изображения, поэтому для них важна директиваimg-src. Если CDN отдаёт CORS-заголовки, виджет уменьшает картинку в браузере; без них он отправляет адрес картинки, и её забирает наш сервер. - Если в вашей политике нет
script-src,connect-srcилиimg-src, браузер используетdefault-src. Добавляйте хосты в ту директиву, которая у вас действительно есть.
Заголовок целиком¶
Магазин, который отдаёт всё со своего домена, а картинки товаров — с cdn.shop.example:
Content-Security-Policy: default-src 'self'; script-src 'self' https://api.ziex-tryon.com; connect-src 'self' https://api.ziex-tryon.com; img-src 'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:; style-src 'self' 'unsafe-inline'
Та же политика с одной директивой на строку, чтобы её было удобнее читать (заголовок должен быть одной строкой):
default-src 'self';
script-src 'self' https://api.ziex-tryon.com;
connect-src 'self' https://api.ziex-tryon.com;
img-src 'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:;
style-src 'self' 'unsafe-inline'
Добавляйте хосты Ziex Try-On в уже существующую политику, а не заменяйте её. Остальные директивы оставьте как есть.
Через тег <meta>¶
Если заголовки задать нельзя, для этих директив подойдёт тег <meta> в <head>:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' https://api.ziex-tryon.com; connect-src 'self' https://api.ziex-tryon.com; img-src 'self' https://cdn.shop.example https://api.ziex-tryon.com https://media.ziex-tryon.com data: blob:; style-src 'self' 'unsafe-inline'">
Поместите его раньше первого <script>. Политика в <meta> не может содержать frame-ancestors, report-uri и
sandbox; для них нужен настоящий заголовок.
Две вещи, которые блокируются при строгой политике¶
1. Inline-обработчик onerror превью товара. В окне показывается маленькое превью вещи. Если картинку не удалось
загрузить, виджет прячет её inline-обработчиком onerror. При script-src без 'unsafe-inline' этот обработчик
блокируется, и сломанное превью остаётся на экране значком битой картинки. Это косметика: на саму примерку она не влияет.
Убедитесь, что адрес картинки товара верный, а её хост есть в img-src.
2. Inline-конфигурация от CMS. Обычный способ передать конфигурацию — inline-скрипт, который вызывает
TryOn.init({ … }), например добавленный через wp_add_inline_script в WordPress. При строгом script-src inline-скрипт
блокируется, если у него нет nonce или хеша. Используйте механизм nonce вашей CMS или фреймворка либо вынесите вызов
init() в небольшой файл скрипта, который вы отдаёте сами и разрешаете через 'self'.
Nonce или хеш в style-src отключает 'unsafe-inline'
Браузеры игнорируют 'unsafe-inline' в директиве, где есть nonce или хеш. Если они есть в вашем style-src,
элемент <style> виджета блокируется, и окно рисуется без стилей. Пока nonce не поддерживается (см. ниже), в
style-src должен быть 'unsafe-inline' без nonce и хеша.
'strict-dynamic'
При 'strict-dynamic' браузер игнорирует имена хостов в script-src. Вместо этого задайте nonce собственным тегам
<script>. Лоадер добавляет скрипт виджета из кода, что 'strict-dynamic' разрешает, если сам лоадер разрешён по
nonce. Проверьте это в консоли, как описано ниже.
Как проверить¶
- Откройте страницу товара с инструментами разработчика на вкладке Console. Откройте окно и нажмите «Примерить»
(достаточно тестового ключа). Браузер выведет строку для каждого заблокированного запроса, например
Refused to connect to 'https://api.ziex-tryon.com/…' because it violates the following Content Security Policy directive: "connect-src …". Директива, названная в сообщении, и есть та, которую нужно исправить. - На вкладке Network заблокированный запрос помечен как
(blocked:csp). - Сначала безопасно выкатите изменение через
Content-Security-Policy-Report-Only: значение то же, но он ничего не блокирует, а только сообщает. Добавьтеreport-uri https://your-endpoint.example/csp(илиreport-to), чтобы собирать отчёты от настоящих посетителей, и переключитесь на блокирующий заголовок, когда отчёты станут чистыми.
Как выглядит каждый сбой:
| Что заблокировано | Что вы увидите |
|---|---|
script-src |
Нет launcher и нет объекта TryOn: window.TryOn равен undefined. |
connect-src |
Launcher нарисован (проверка, которая его прячет при исчерпанном лимите, при ошибке пропускает), но примерка заканчивается сообщением о потере соединения. |
img-src |
Битые картинки: превью вещи, результат или миниатюры в «Моих образах». |
style-src |
Окно появляется без стилей. |
Что изменится дальше¶
В одном из следующих выпусков виджета необходимость 'unsafe-inline' в style-src исчезнет: виджет будет рисоваться
без inline-стилей и сможет принимать nonce со страницы. Это ещё не выпущено. Пока этого нет, используйте директивы
выше. Когда это появится, здесь будет сказано об этом, а перечисленные здесь директивы продолжат работать.
См. также: справочник по виджету, отложенная загрузка и подхват.