如果您尝试在最新版本的 Chrome 上getUserMedia()
使用跨源 iframe访问相机和麦克风,默认情况下它将失败。
我们已经多次遇到过这种情况,因为Pipe 音频和视频录制平台的用户试图将 Pipe 嵌入到使用 iframe 嵌入外部 HTML 和 JS 代码的Wix网站或Google 站点中。
原因源于 2017 年和 2018 年对 Chrome 进行的一系列安全和隐私更改:
- Chrome 60 引入了功能策略,为开发人员提供了一种方法来控制其网站内敏感功能的使用
- 默认情况下, Chrome 64 会阻止跨源 iframe 中的摄像头和麦克风访问,并且需要功能策略才能授予访问权限
功能策略允许您控制浏览器中网站可用的敏感 API 和功能。Feature-Policy
您可以通过HTTP 标头或使用allow
HTML iframe 中的属性来控制这些功能是否可用。
敏感功能现在包括:
- 访问
camera
和microphone
通过getUserMedia()
fullscreen
API _geolocation
API _- 访问加速度计或 USB 设备
您可以查看Chrome 的来源以获取受功能策略控制的最新功能列表,或查看 chromestatus.com以获取考虑实施的策略列表。
下面,我们将重点关注allow
iframe 中与摄像头和麦克风访问相关的属性,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 添加任何嵌入内容:
在 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 。更多细节可以在这里找到。
进一步阅读:
- 功能政策介绍
- Chrome 中默认禁用跨域 iframe 的功能。这些功能必须通过功能策略在 iframe 中专门启用。
- 功能政策规范