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

管理网页以及网页上的第三方 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 属性即可访问该功能。

因此,我们建议开发者在响应中明确设置权限政策标头,以便阻止源列表中未列出的跨源 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")

并将 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 是从未添加到来源列表且在 iframe 代码上设置了 allow 属性的其他子网域 (subdomain.your-site-example) 中投放的,则会被禁止使用此功能。不同的子网域会被视为同一网站,但跨源。
  4. 添加到来源列表且在 iframe 代码上设置了 allow 属性的跨源 iframe (trusted-site.example) 可以使用此功能。
  5. 如果向来源列表添加了没有 allow 属性的跨源 iframe (trusted-site.example),则该 iframe 将被禁止使用该功能。
  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 已添加到源列表,也会被屏蔽,因为权限政策会委托权限。您还可以使用 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 将无法访问地理定位功能。只有在来源列表中列出且 iframe 标记中包含 allow 属性的原始网页和 https://trusted-site.example 才能访问用户的功能。

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

功能在所有来源上均被屏蔽

被禁止访问该功能的所有来源的架构

Permissions-Policy: geolocation=()

如果源站列表为空,系统会对所有源站屏蔽该功能。您可以在演示中查看此设置。

使用 JavaScript API

功能政策的现有 JavaScript API 在文档或元素 (document.featurePolicy or element.featurePolicy) 上显示为对象。尚未实现权限政策的 JavaScript API。

Feature Policy API 可用于由权限政策设置的政策,但存在一些限制。关于 JavaScript API 实现,还有其他问题,并且我们已提出将逻辑移至 Permissions API提案。如果您有任何想法,欢迎参与讨论。

featurePolicy.allowsFeature(feature)

  • 如果允许对默认来源使用该功能,则返回 true
  • 由权限政策和之前的功能政策设置的政策的行为相同
  • 对 iframe 元素 (iframeEl.featurePolicy.allowsFeature('geolocation')) 调用 allowsFeature() 时,返回值反映了 iframe 上是否设置了 allow 属性

featurePolicy.allowsFeature(feature, origin)

  • 如果允许为指定来源使用该功能,则返回 true
  • 如果在 document 上调用了此方法,则此方法不会再像功能政策那样告知您,是否允许指定来源使用相应地图项。现在,此方法会告知您,该功能可能会被允许用于该来源。您必须额外检查 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()

  • 返回允许使用默认来源的功能列表。
  • 由权限政策和功能政策设置的两项政策的行为相同
  • 如果关联的节点是 iframe,系统会考虑 allow 属性。

featurePolicy.features()

  • 返回浏览器中提供的功能列表。
  • 对于通过“权限政策”设置的政策和功能政策设置的政策,其行为相同

Chrome DevTools 集成

Chrome 开发者工具与 Permissions Policy 的集成

查看开发者工具中权限政策的运作方式。

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

从 Feature-Policy 迁移

如果您使用的是 Feature-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) 方法,而不是包含的 documentelement.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 for Permissions Policy 违规问题则作为实验性功能提供。

如果您想测试此实验性功能,请按照演示操作,然后在 chrome://flags/#enable-experimental-web-platform-features 中启用该标志。启用该标志后,您可以在 DevTools 的“Application”标签页下观察权限政策违规情况:

以下示例展示了如何构建 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”的端点(如前面的示例所示),您可以接收该框架内出现的任何违规行为的报告。子框架需要自己的报告配置。

了解详情

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