如果您尝试在最新版本的 Chrome 上getUserMedia()使用跨源 iframe访问相机和麦克风,默认情况下它将失败。

我们已经多次遇到过这种情况,因为Pipe 音频和视频录制平台的用户试图将 Pipe 嵌入到使用 iframe 嵌入外部 HTML 和 JS 代码的Wix网站或Google 站点中。

原因源于 2017 年和 2018 年对 Chrome 进行的一系列安全和隐私更改:

  1. Chrome 60 引入了功能策略,为开发人员提供了一种方法来控制其网站内敏感功能的使用
  2. 默认情况下, Chrome 64 会阻止跨源 iframe 中的摄像头和麦克风访问,并且需要功能策略才能授予访问权限

功能策略允许您控制浏览器中网站可用的敏感 API 和功能。Feature-Policy您可以通过HTTP 标头或使用allowHTML iframe 中的属性来控制这些功能是否可用。

敏感功能现在包括:

  • 访问cameramicrophone通过getUserMedia()
  • fullscreenAPI _
  • geolocationAPI _
  • 访问加速度计或 USB 设备

您可以查看Chrome 的来源以获取受功能策略控制的最新功能列表,或查看 chromestatus.com以获取考虑实施的策略列表。

下面,我们将重点关注allowiframe 中与摄像头和麦克风访问相关的属性,getUserMedia()有关功能策略的更详细概述,请查看这篇出色的介绍文章

HTML 元素的allow属性使您能够控制该iframe 中可用的敏感功能。语法很简单,它有以下形式:iframe

<iframe src="" allow="feature_name allow_list"></iframe>

您可以使用分号为多个功能指定允许列表:

<iframe src="" allow="feature_name allow_list;feature_name allow_list"></iframe>

因此,要允许跨源 iframe 中的摄像头和麦克风访问,您需要将以下allow属性添加到 iframe:

<!--Allow camera and microphone access within the context of this iframe-->
<iframe src="https://example.com" allow="camera;microphone"></iframe>

这相当于:

<!--Allow camera and microphone access within the context of this iframe-->
<iframe src="https://example.com" allow="camera *;microphone *"></iframe>

以上将允许托管在任何域上的任何页面在通过上述 iframe 加载时请求访问用户的相机和麦克风。

为了收紧,您可以更详细地了解哪些域可以访问这些功能,因为它们allow_list可以具有以下任何值:

  • *:在上面使用,该功能允许在顶级浏览上下文和嵌套上下文(iframe)中使用
  • 'self':在顶级浏览上下文和同源嵌套上下文中允许该功能。嵌套浏览上下文的跨域文档中不允许使用该功能。
  • 'none':在顶级和嵌套浏览上下文中根本不允许该功能。
  • <origin(s)>:该功能在特定来源中是允许的,例如https://my_website.com

如果没有上述 iframeallow属性,则在实施了功能策略的浏览器中的跨源 iframe 中将不允许摄像头和麦克风访问(请参阅下面的浏览器支持)。如果您正在侦听getUserMedia()错误,您将得到一个NotAllowedError因为功能策略阻止的请求以与用户拒绝权限提示类似的方式失败。

这就是为什么我们自己的管道录音机在嵌入使用Wix构建的网站时无法在 Chrome 中访问摄像头和麦克风的原因。 Wix 通过没有所需allow属性的跨源 iframe 添加任何嵌入内容:

用于嵌入的 Wix iframe 代码缺少功能策略的允许属性

在 Feature Policy 发布之前,摄像头和麦克风 API 已经由名为 的旧属性控制allowusermedia,但现在已弃用此属性,您应该使用allow具有正确值的新属性来控制访问。

如果同时指定了旧属性和新属性,则更严格的策略将优先(在 Chrome 中)。例如,不允许以下 iframe 请求访问摄像头,因为allow="camera 'none'"它比 更具限制性allowusermedia

<iframe allowusermedia allow="camera 'none'" src="https://example.com"></iframe>

记住 iframe 继承其父页面的功能策略设置非常重要,这意味着如果页面和 iframe 都指定了功能策略列表,则将应用更严格的策略。因此,如果您的 iframe 中的功能仍然不起作用,请确保没有通过父页面上的 HTTP 标头施加更严格的策略。

浏览器支持

Chrome 60allow引入了对 HTTP 标头和属性的功能策略支持,根据我们的测试,其他基于 Chromium 的浏览器也支持该功能,例如Opera和基于 Chromium的新 Edge 。

有关支持该功能的浏览器的完整列表,请参阅 caniuse.com

Chrome 74还引入了一个 JavaScript API,允许您检测 iframe、页面或浏览器允许哪些功能。frame.featurePolicy您可以使用iframe 或document.featurePolicy页面/浏览器/主文档访问 API 。更多细节可以在这里找到。

进一步阅读:

使用 getUserMedia 和功能策略在跨域 iframe 中访问相机和麦克风