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

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

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

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

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

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

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

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

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

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

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

Раньше с политикой функций.

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

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

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

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

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

Политику функций по-прежнему можно использовать после Chrome 88, но она действует как псевдоним Политики разрешений. Кроме синтаксиса, в логике нет никакой разницы. Если заголовки 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 ), который не был добавлен в исходный список и для которого в теге iframe установлен атрибут разрешения, не может использовать эту функцию. Различные поддомены считаются одним и тем же сайтом, но имеют перекрестное происхождение.
  4. iframe из разных источников ( trusted-site.example ), который был добавлен в список источников и для которого в теге iframe установлен атрибут allow , может использовать эту функцию.
  5. iframe из разных источников ( trusted-site.example ), добавленный в список источников без атрибута allow , блокируется от использования этой функции.
  6. iframe из разных источников ( ad.example ), который не был добавлен в исходный список, не может использовать эту функцию, даже если allow включен в тег iframe.

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

Пользователь делает запрос, сервер отвечает заголовком 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 имеют доступ к функции геолокации в браузере пользователя. . Помните, что атрибут разрешения также должен быть установлен в самом 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 , указанные в исходном списке вместе с атрибутом разрешения в теге iframe, будут иметь доступ к функции пользователя.

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

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

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

Permissions-Policy: geolocation=()

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

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

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

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

FeaturePolicy.allowsFeature(функция)

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

FeaturePolicy.allowsFeature(функция, происхождение)

  • Возвращает true если функция разрешена для указанного источника.
  • Если метод вызывается для document , этот метод больше не сообщает вам, разрешена ли функция для указанного источника, как это сделала Feature Policy. Теперь этот метод сообщает вам, что объекту можно разрешить доступ к этому источнику. Необходимо провести дополнительную проверку того, установлен ли в iframe атрибут allow или нет. Разработчик должен провести дополнительную проверку атрибута 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 .
  2. Откройте панель приложения , чтобы проверить разрешенные и запрещенные функции каждого кадра.
  3. На боковой панели выберите кадр, который вы хотите проверить. Вам будет представлен список функций, которые разрешено использовать выбранному фрейму, и список функций, которые заблокированы в этом фрейме.

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

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

Замените заголовки Feature Policy заголовками Permissions 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 на вкладке «Приложение»:

В следующем примере показано, как можно создать заголовок Reporting 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;

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

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

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