使用权限政策控制浏览器功能

管理您的网页和网页上的第三方 iframe 如何访问浏览器功能。

Kevin K. Lee
Kevin K. Lee

权限政策(以前称为功能政策)允许开发者通过声明一组供浏览器强制执行的政策来控制网页、其 iframe 和子资源可用的浏览器功能。这些政策适用于响应标头来源列表中提供的来源。来源列表可以包含同源来源和跨源来源,并且允许开发者控制第一方和第三方对浏览器功能的访问权限。

用户可以自行决定是否允许访问更强大的功能,并且需要通过接受提示来明确授予权限。

权限政策允许顶级网站定义其自身及其第三方打算使用的功能,从而减轻用户确定功能访问请求是否合法的负担。例如,通过使用权限政策来阻止所有第三方使用地理定位功能,开发者可以确保没有任何第三方会获得用户的地理定位信息。

“权限”政策的变更

权限政策以前称为功能政策。核心概念保持不变,但名称更改后,还带来了一些重要变化。

结构化字段的用法

结构化字段提供了一组通用数据结构,用于标准化 HTTP 标头字段值的解析和序列化。如需详细了解结构化字段,请参阅 Fastly 的博文“通过结构化标头字段改进 HTTP”。

旧优惠
  geolocation 'self' https://example.com; camera 'none'

之前(使用特性政策)。

  geolocation=(self "https://example.com"), camera=()

现在,借助“权限”政策。

将标头与 iframe allow 属性结合使用

借助功能政策,您可以通过以下方式将功能添加到跨源框架:将来源添加到标头来源列表,或向 iframe 标记添加 allow 属性。借助权限政策,如果您将跨源框架添加到来源列表,则相应来源的 iframe 标记必须包含 allow 属性。如果响应不包含权限政策标头,则来源列表将被视为具有默认值 *。向 iframe 添加 allow 属性可实现对该功能的访问。

因此,我们建议开发者在响应中明确设置 Permissions Policy 标头,以便阻止未在来源列表中列出的跨源 iframe 访问此功能,即使存在 allow 也是如此。

在 Chrome 88 之后,仍可使用功能政策,但它会充当权限政策的别名。除了语法之外,逻辑方面没有任何区别。如果同时使用权限政策和功能政策标头,Permissions-Policy 标头的优先级会更高,并将覆盖 Feature-Policy 标头提供的值。

如何使用权限政策?

简要概述

在深入探讨之前,我们先快速了解一个常见场景:您是网站所有者,希望控制您的网站和第三方代码如何使用浏览器功能。

  • 您的网站为 https://your-site.example
  • 您的网站嵌入了来自同源 (https://your-site.example) 的 iframe。
  • 您的网站嵌入了来自您信任的 https://trusted-site.example 的 iframe。
  • 您的网站还展示由 https://ad.example 投放的广告。
  • 您希望仅允许您的网站和受信任的网站使用地理定位,而不允许广告使用地理定位。

在这种情况下,请使用以下标头:

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

并为可信网站的 iframe 代码明确设置 allow 属性:

<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 代码中设置了 allow 属性,则该 iframe 将无法使用该功能。不同的子网域会被视为同网站但跨源。
  4. 已添加到来源列表且在 iframe 代码中设置了 allow 属性的跨源 iframe (trusted-site.example) 可以使用该功能。
  5. 添加到来源列表中的跨源 iframe (trusted-site.example) 如果没有 allow 属性,则无法使用该功能。
  6. 未添加到来源列表中的跨源 iframe (ad.example) 会被禁止使用该功能,即使 iframe 代码中包含 allow 属性也是如此。

Permissions-Policy HTTP 响应标头

用户发出请求,服务器以权限政策标头进行响应,然后浏览器根据该标头授予访问权限。

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")
    • selfhttps://your-site.example 的简写
  • 语法:[FEATURE]=([ORIGIN(s)])
    • 应用于同一来源和指定来源的政策
    • 示例:geolocation=("https://your-site.example" "https://a.example" "https://b.example")
    • 使用此语法时,其中一个来源应为嵌入者的来源。如果嵌入网页本身未获得相应权限,则即使将该网页中嵌入的 iframe 添加到来源列表,这些 iframe 也会被屏蔽,因为权限政策会委托权限。您还可以使用 self 令牌。
  • 语法:[FEATURE]=()
    • 为所有源站屏蔽了该功能
    • 示例:geolocation=()

不同的子网域和路径

不同的子网域(例如 https://your-site.examplehttps://subdomain.your-site.example)被视为同网站但跨源。因此,在源列表中添加子网域并不会允许访问同一网站的其他子网域。每个想要使用该功能的嵌入式子网域都必须单独添加到来源列表中。例如,如果仅允许通过标头 Permissions-Policy: browsing-topics=(self) 对用户浏览主题进行同源访问,则来自同一网站的不同子网域 (https://subdomain.your-site.example) 的 iframe 将无法访问这些主题。

不同的路径(例如 https://your-site.examplehttps://your-site.example/embed)被视为同源,因此无需在来源列表中列出不同的路径。

iframe allow 属性

iframe 设置

对于跨源使用,iframe 需要在标记中添加 allow 属性才能获得对该功能的访问权限。

语法:<iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>

例如:

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

处理 iframe 导航

iframe 导航设置

默认情况下,如果 iframe 导航到其他来源,则该政策不会应用于 iframe 导航到的来源。通过在 allow 属性中列出 iframe 导航到的来源,应用于原始 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 本身中设置 allow 属性。

您可以在演示中看到此设置。

仅允许在同源中使用此功能

仅允许同源访问该功能的架构

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。请务必向 iframe 标记显式添加 allow 属性。如果存在另一个具有 <iframe src="https://ad.example" allow="geolocation"> 的 iframe,则 https://ad.example 将无法访问地理定位功能。只有原始网页和来源列表中列出的 https://trusted-site.example 且 iframe 代码中包含 allow 属性的来源才能访问用户的功能。

您可以在演示中看到此设置。

在所有来源中屏蔽了该功能

被阻止访问相应功能的所有来源的架构

Permissions-Policy: geolocation=()

如果源列表为空,则该功能会针对所有来源被屏蔽。您可以在演示中看到此设置。

使用 JavaScript API

功能政策的现有 JavaScript API 可在文档或元素 (document.featurePolicy or element.featurePolicy) 上找到。权限政策的 JavaScript API 尚未实现。

功能政策 API 可用于权限政策设置的政策,但存在一些限制。关于 JavaScript API 实现,目前仍存在一些未解决的问题,并且有人提议将逻辑移至 Permissions API 中。如果您有任何想法,欢迎参与讨论。

featurePolicy.allowsFeature(feature)

  • 如果允许将该功能用于默认来源,则返回 true
  • 无论是通过 Permissions Policy 还是之前的 Feature Policy 设置的政策,行为都是相同的
  • 当对 iframe 元素 (iframeEl.featurePolicy.allowsFeature('geolocation')) 调用 allowsFeature() 时,返回值会反映 iframe 上是否设置了 allow 属性

featurePolicy.allowsFeature(feature, origin)

  • 如果允许指定来源使用相应功能,则返回 true
  • 如果该方法是在 document 上调用的,则该方法不再像 Feature Policy 那样告知您指定来源是否允许使用相应功能。现在,此方法会告知您,该功能可能允许用于相应来源。您必须额外检查 iframe 是否设置了 allow 属性。开发者必须对 iframe 元素上的 allow 属性进行额外检查,以确定第三方来源是否允许使用该功能。

使用 element 对象检查 iframe 中的功能

您可以改用 element.allowsFeature(feature),它会考虑 allow 属性,而 document.allowsFeature(feature, origin) 不会。

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

featurePolicy.allowedFeatures()

  • 返回允许用于默认来源的功能列表。
  • 无论是通过 Permissions Policy 还是 Feature Policy 设置的政策,行为都相同
  • 如果关联的节点是 iframe,则会考虑 allow 属性。

featurePolicy.features()

  • 返回浏览器中可用的功能列表。
  • 无论是通过 Permissions Policy 还是 Feature Policy 设置的政策,行为都相同

Chrome 开发者工具集成

Chrome 开发者工具与权限政策的集成

了解权限政策在开发者工具中的运作方式。

  1. 打开 Chrome 开发者工具
  2. 打开应用面板,查看每个框架的允许功能和禁止功能。
  3. 在边栏中,选择要检查的帧。系统会显示所选框架允许使用的功能列表,以及在该框架中被屏蔽的功能列表。

从 Feature-Policy 迁移

如果您使用的是 Feature-Policy 标头,可以按照以下步骤迁移到权限政策。

将 Feature Policy 标头替换为 Permissions Policy 标头

由于基于 Chromium 的浏览器才支持功能政策标头,而权限政策标头自 Chrome 88 起才受支持,因此可以放心地使用权限政策更新现有标头。

旧优惠
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 的允许功能,请使用附加在 iframe 元素上的 allowsFeature(feature) 方法,而不是包含的 document。方法 element.allowsFeature(feature) 会考虑 allow 属性,而 document.allowsFeature(feature, origin) 不会。

使用 document 查看功能访问权限

如需继续使用 document 作为基本节点,您必须对 iframe 标记上的 allow 属性进行额外检查。

<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

建议您对 element 对象调用 allowsFeature(),而不是使用 document 更新现有代码,如上一个示例所示。

Reporting API

Reporting API 以一致的方式为 Web 应用提供报告机制,而针对权限政策违规行为的 Reporting API 可作为实验性功能使用。

如果您想测试实验性功能,请按照演练中的步骤操作,并在 chrome://flags/#enable-experimental-web-platform-features 中启用相应标志。启用该标志后,您可以在开发者工具的“应用”标签页下观察权限政策违规情况:

以下示例展示了如何构建 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;

在当前实现中,您可以通过配置名为“default”的端点(如前面的示例所示)来接收该框架内发生的任何违规行为的政策违规报告。子框架将需要自己的报告配置。

了解详情

如需深入了解权限政策,请参阅以下资源: