Управляйте функциями браузера с помощью политики разрешений

Управляйте доступом вашей страницы и сторонних фреймов на ней к функциям браузера.

Кевин К. Ли
Kevin K. Lee

Политика разрешений (Permissions Policy), ранее известная как политика функций (Feature Policy), позволяет разработчику контролировать функции браузера, доступные для страницы, её фреймов (iframe) и подресурсов, декларируя набор политик, которые браузер будет применять. Эти политики применяются к источникам, указанным в списке источников в заголовке ответа. Список источников может содержать как те же источники, так и кросс-источники, и позволяет разработчику контролировать доступ как основных, так и сторонних пользователей к функциям браузера.

Пользователь принимает окончательное решение о предоставлении доступа к более мощным функциям и должен предоставить явное разрешение, приняв запрос.

Политика разрешений позволяет сайту верхнего уровня определять, что он и его третьи стороны намерены использовать, и снимает с пользователя бремя проверки законности запроса на доступ к функции. Например, блокируя функцию геолокации для всех третьих сторон с помощью политики разрешений, разработчик может быть уверен, что никакая третья сторона не получит доступ к геолокации пользователя.

Изменения в политике разрешений

Политика разрешений ранее называлась Политикой функций. Основные концепции остались прежними, но помимо названия произошли и некоторые важные изменения.

Использование структурированных полей

Структурированные поля предоставляют набор распространённых структур данных для стандартизации анализа и сериализации значений полей HTTP-заголовков. Подробнее о структурированных полях можно узнать в статье блога Fastly « Улучшение HTTP с помощью структурированных полей заголовков ».

Старый
  geolocation 'self' https://example.com; camera 'none'

До с Политикой функций.

Новый
  geolocation=(self "https://example.com"), camera=()

Теперь с политикой разрешений.

Объедините заголовки с атрибутом allow iframe

С помощью политики функций вы можете добавить функцию во фрейм с кросс-источниками, добавив источник в список источников заголовка или атрибут allow в тег iframe. С помощью политики разрешений, если вы добавляете фрейм с кросс-источниками в список источников, тег iframe для этого источника должен включать атрибут allow . Если ответ не содержит заголовка политики разрешений, считается, что список источников имеет значение по умолчанию * . Добавление атрибута allow в тег iframe разрешает доступ к функции.

Поэтому мы рекомендуем разработчикам явно указывать заголовок «Политика разрешений» в ответе, чтобы кросс-источниковые iframe, не указанные в списке источников, не имели доступа к этой функции, даже если присутствует allow .

Feature Policy можно использовать и после Chrome 88, но он действует как псевдоним для Permissions Policy. За исключением синтаксиса, логика ничем не отличается. Если оба заголовка Permissions Policy и Feature Policy используются одновременно, заголовок Permissions-Policy будет иметь более высокий приоритет и перезапишет значение, предоставленное заголовком Feature-Policy .

Как использовать политику разрешений?

Краткий обзор

Прежде чем углубляться в детали, кратко рассмотрим распространенный сценарий, когда вы являетесь владельцем веб-сайта и хотите контролировать, как ваш сайт и сторонний код используют функции браузера.

  • Ваш сайт — https://your-site.example .
  • На вашем сайте встроен iframe из того же источника ( https://your-site.example ).
  • На вашем сайте встроен iframe из https://trusted-site.example которому вы доверяете.
  • На вашем сайте также отображаются объявления, обслуживаемые https://ad.example .
  • Вы хотите разрешить геолокацию только для своего сайта и доверенного сайта, а не для рекламы.

В этом случае используйте следующий заголовок:

Permissions-Policy: geolocation=(self "https://trusted-site.example")

И явно задайте атрибут allow для тега iframe для доверенного сайта:

<iframe src="https://trusted-site.example" allow="geolocation">

Краткий обзор использования политики разрешений.

В этом примере список источников заголовков позволяет использовать функцию геолокации только вашему сайту ( self ) и trusted-site.example . ad.example не имеет права использовать геолокацию.

  1. Вашему сайту your-site.example разрешено использовать функцию геолокации с согласия пользователя.
  2. Для iframe того же источника ( your-site.example ) разрешено использовать эту функцию без использования атрибута allow .
  3. iframe, размещенный с другого поддомена ( subdomain.your-site-example ), который не был добавлен в список источников и имеет атрибут allow в теге iframe, блокирует использование этой функции. Разные поддомены считаются принадлежащими одному сайту, но кросс-доменными.
  4. Кросс-источник iframe ( trusted-site.example ), добавленный в список источников и имеющий атрибут allow установленный в теге iframe, может использовать эту функцию.
  5. Кросс-источниковый iframe ( trusted-site.example ), добавленный в список источников без атрибута allow , блокирует использование этой функции.
  6. Кросс-источниковый iframe ( ad.example ), который не был добавлен в список источников, блокирует использование этой функции, даже если атрибут allow включен в тег iframe.

Заголовок ответа HTTP Permissions-Policy

Пользователь делает запрос, сервер отвечает заголовком «Политика разрешений», а затем браузер предоставляет доступ на основе этого заголовка.

Permissions-Policy: <feature>=(<token>|<origin(s)>)

Используйте заголовок Permissions-Policy в ответе сервера, чтобы задать разрешённые источники для функции. Значение заголовка может содержать комбинацию токенов и строк источников. Доступные токены : * для всех источников и self для одного и того же источника.

Если заголовок предназначен для нескольких функций, разделяйте их запятыми. Если вы перечисляете несколько источников, разделяйте каждый источник в списке пробелом. Для заголовков, в которых указан источник, являющийся запросом кросс-источника, тег iframe должен включать атрибут allow .

Вот несколько примеров пар «ключ-значение»:

  • Синтаксис: [FEATURE]=*
    • Политика применяется ко всем источникам
    • Пример: geolocation=*
  • Синтаксис: [FEATURE]=(self)
    • Политика применяется к тому же происхождению
    • Пример: geolocation=(self)
  • Синтаксис: [FEATURE]=(self [ORIGIN(s)])
    • Политика применяется к одному и тому же источнику и указанным источникам
    • Пример: geolocation=(self "https://a.example" "https://b.example")
    • self — это сокращение от https://your-site.example
  • Синтаксис: [FEATURE]=([ORIGIN(s)])
    • Политика применяется к одному и тому же источнику и указанным источникам
    • Пример: geolocation=("https://your-site.example" "https://a.example" "https://b.example")
    • При использовании этого синтаксиса одним из источников должен быть источник встраиваемого приложения. Если самой странице встраиваемого приложения не предоставлены разрешения, встроенные на этой странице iframe также будут заблокированы, даже если они добавлены в список источников, поскольку политика разрешений делегирует разрешения. Вы также можете использовать токен self .
  • Синтаксис: [FEATURE]=()
    • Функция заблокирована для всех источников
    • Пример: geolocation=()

Различные поддомены и пути

Разные поддомены, такие как https://your-site.example и https://subdomain.your-site.example , считаются поддоменами одного и того же сайта, но с кросс-доменом . Поэтому добавление поддомена в список источников не разрешает доступ к другому поддомену того же сайта. Каждый встроенный поддомен, который хочет использовать эту функцию, должен быть добавлен в список источников отдельно. Например, если доступ к темам просмотра пользователя разрешен только для того же источника с заголовком Permissions-Policy: browsing-topics=(self) , iframe из другого поддомена того же сайта, https://subdomain.your-site.example , не будет иметь доступа к этим темам.

Различные пути, такие как https://your-site.example и https://your-site.example/embed , считаются принадлежащими одному и тому же источнику, и различные пути не обязательно должны быть указаны в списке источников.

Атрибут allow iframe

Настройка iframe

Для использования в разных источниках iframe должен иметь атрибут allow в теге, чтобы получить доступ к функции.

Синтаксис: <iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>

Например:

<iframe src="https://trusted-site.example" allow="geolocation">

Управление навигацией iframe

Настройка навигации Iframe

По умолчанию, если iframe переходит в другой источник, политика не применяется к источнику, к которому переходит iframe. Если указать источник, к которому переходит iframe, в атрибуте allow , политика разрешений, примененная к исходному iframe, будет применена к источнику, к которому переходит iframe.

<iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example">

Вы можете увидеть это в действии, посетив демонстрационную версию навигации iframe .

Примеры настроек политики разрешений

Примеры следующих настроек можно найти в демо-версии .

Функция разрешена для всех источников

Архитектура любого происхождения имеет право доступа к функции

Permissions-Policy: geolocation=*
<iframe src="https://trusted-site.example" allow="geolocation">
<iframe src="https://ad.example" allow="geolocation">

Если в списке источников задан токен * , функция разрешена для всех источников на странице, включая саму страницу и все iframe. В этом примере весь код, передаваемый с https://your-site.example , а также коды, передаваемые с https://trusted-site.example iframe и https://ad.example имеют доступ к функции геолокации в браузере пользователя. Помните, что атрибут allow также должен быть установлен для самого iframe вместе с добавлением источника в список источников заголовка.

Эту настройку можно увидеть в демо-версии .

Функция разрешена только в том же источнике

Доступ к функции разрешен только архитектуре того же происхождения.

Permissions-Policy: geolocation=(self)

Использование токена self позволяет использовать геолокацию только для одного и того же источника. Доступ к этой функции будет закрыт для пользователей из разных источников. В этом примере доступ к геолокации будет только у https://trusted-site.example ( self ). Используйте этот синтаксис, если хотите, чтобы эта функция была доступна только для вашей страницы и ни для кого другого.

Эту настройку можно увидеть в демо-версии .

Функция разрешена для одного и того же источника и определенных перекрестных источников

Архитектура указанного происхождения разрешила доступ к функции

Permissions-Policy: geolocation=(self "https://trusted-site.example")

Этот синтаксис позволяет использовать геолокацию как для себя ( https://your-site.example ), так и для https://trusted-site.example . Не забудьте явно добавить атрибут allow в тег iframe. Если есть другой iframe с <iframe src="https://ad.example" allow="geolocation"> , то у https://ad.example не будет доступа к функции геолокации. Доступ к функции пользователя будет иметь только исходная страница и https://trusted-site.example , указанный в списке источников и имеющий атрибут allow в теге iframe.

Эту настройку можно увидеть в демо-версии .

Функция заблокирована для всех источников

Архитектура любого происхождения заблокирована от доступа к этой функции

Permissions-Policy: geolocation=()

При пустом списке источников эта функция блокируется для всех источников. Эту настройку можно увидеть в демо-версии .

Используйте JavaScript API

Существующий JavaScript API для Feature Policy представлен как объект в документе или элементе ( document.featurePolicy or element.featurePolicy ). JavaScript API для Permissions Policy пока не реализован.

API политики функций можно использовать для политик, установленных политикой разрешений, с некоторыми ограничениями. Остались вопросы по реализации JavaScript API, и было предложено перенести логику в API разрешений . Присоединяйтесь к обсуждению, если у вас есть какие-либо идеи.

featurePolicy.allowsFeature(feature)

  • Возвращает значение true , если функция разрешена для использования в источнике по умолчанию.
  • Поведение одинаково для обеих политик, установленных политикой разрешений и предыдущей политикой функций.
  • Когда allowsFeature() вызывается для элемента iframe ( iframeEl.featurePolicy.allowsFeature('geolocation') ), возвращаемое значение отражает, установлен ли атрибут allow для iframe

featurePolicy.allowsFeature(feature, origin)

  • Возвращает значение true , если функция разрешена для указанного источника.
  • Если метод вызывается для document , он больше не сообщает, разрешена ли функция для указанного источника, как это делал Feature Policy. Теперь этот метод сообщает, что функция может быть разрешена для этого источника. Необходимо провести дополнительную проверку того, установлен ли атрибут allow для элемента iframe. Разработчик должен провести дополнительную проверку атрибута allow для элемента iframe, чтобы определить, разрешена ли функция для стороннего источника.

Проверьте наличие функций в iframe с помощью объекта element

Вы можете использовать element.allowsFeature(feature) , который учитывает атрибут allow, в отличие от document.allowsFeature(feature, origin) , который этого не делает.

const someIframeEl = document.getElementById('some-iframe')
const isCameraFeatureAllowed = someIframeEl.featurePolicy.allowsFeature('camera')

featurePolicy.allowedFeatures()

  • Возвращает список функций, разрешенных для использования в источнике по умолчанию.
  • Поведение одинаково для обеих политик, установленных политикой разрешений и политикой функций.
  • Если связанный узел является iframe, учитывается атрибут allow.

featurePolicy.features()

  • Возвращает список функций, доступных в браузере.
  • Поведение одинаково для обеих политик, установленных политикой разрешений и политикой функций.

Интеграция с Chrome DevTools

Интеграция Chrome DevTools с политикой разрешений

Узнайте, как работает политика разрешений в DevTools.

  1. Откройте Chrome DevTools .
  2. Откройте панель приложений , чтобы проверить разрешенные и запрещенные функции каждого кадра.
  3. На боковой панели выберите фрейм, который вы хотите проверить. Вам будет представлен список функций, которые разрешено использовать выбранному фрейму, и список функций, которые заблокированы в этом фрейме.

Миграция из Feature-Policy

Если вы используете заголовок Feature-Policy , вы можете выполнить следующие шаги для перехода на политику разрешений.

Заменить заголовки политики функций на заголовки политики разрешений

Поскольку заголовки Feature Policy поддерживаются только в браузерах на базе Chromium, а заголовки Permissions Policy поддерживаются с Chrome 88 , можно безопасно обновить существующие заголовки с помощью Permissions Policy.

Старый
Feature-Policy:
  autoplay *;
  geolocation 'self';
  camera 'self' 'https://trusted-site.example';
  fullscreen 'none';

До с Политикой функций.

Новый
Permissions-Policy:
  autoplay=*,
  geolocation=(self),
  camera=(self "https://trusted-site.example"),
  fullscreen=()

Теперь с политикой разрешений.

Обновить использование document.allowsFeature(feature, origin)

Если вы используете метод document.allowsFeature(feature, origin) для проверки разрешённых функций для iframe, используйте метод allowsFeature(feature) прикреплённый к элементу iframe, а не к содержащему document . Метод element.allowsFeature(feature) учитывает атрибут allow, а document.allowsFeature(feature, origin) нет.

Проверить доступ к функциям с помощью document

Чтобы продолжить использовать document в качестве базового узла, необходимо провести дополнительную проверку атрибута allow в теге iframe.

<iframe id="some-iframe" src="https://example.com" allow="camera"></iframe>
Permissions-Policy: camera=(self "https://example.com")
const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com')

const someIframeEl = document.getElementById('some-iframe')
const hasCameraAttributeValue = someIframeEl.hasAttribute('allow')
&& someIframeEl.getAttribute('allow').includes('camera')

const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue

Вместо обновления существующего кода с помощью document рекомендуется вызвать allowsFeature() для объекта element , как в предыдущем примере.

API отчетности

API отчетности обеспечивает механизм отчетности для веб-приложений согласованным образом, а API отчетности о нарушениях политики разрешений доступен в качестве экспериментальной функции.

Если вы хотите протестировать экспериментальную функцию, следуйте пошаговому руководству и включите флаг в chrome://flags/#enable-experimental-web-platform-features . Если флаг включён, вы сможете отслеживать нарушения политики разрешений в DevTools на вкладке «Приложение»:

В следующем примере показано, как может быть построен заголовок API отчетов:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;

В текущей реализации вы можете получать отчёты о нарушениях политики, возникающих в пределах данного фрейма, настроив конечную точку с именем «default», как в предыдущем примере. Для подфреймов потребуется собственная конфигурация отчётности.

Узнать больше

Для более глубокого понимания политики разрешений обратитесь к следующим ресурсам: