allow属性是iframe的显式白名单机制,用于声明子页面可调用的浏览器API及对应来源;未列入的API默认禁用,调用即抛NotAllowedError,且语法必须严格满足“特性=来源列表”格式,分号分隔,括号包裹来源。

allow 属性不是“开关”,而是显式白名单
浏览器默认禁止 iframe 内所有敏感 API 调用,allow 不是“打开权限”,而是声明“哪些特性 + 哪些来源”被明确允许。没写进 allow 的,哪怕只漏一个 geolocation,调用 navigator.geolocation.getCurrentPosition() 就会直接抛 NotAllowedError,不会弹窗、不走用户授权流程。
常见误判:以为写了 allow="geolocation" 就够了 → 实际缺少来源列表,等价于未授权;以为 allow="*" 能开全功能 → 它只表示“同源 iframe 可用所有特性”,跨域 iframe 仍受严格限制,且现代浏览器对 * 的支持已弱化。
-
allow="geolocation 'self'":仅允许 iframe 自身源(非父页面源)调用定位 -
allow="geolocation 'self' https://maps.example.com":多来源需空格分隔,且必须在括号内 -
allow="geolocation=()":显式禁用,比省略更可靠,优先级高于响应头
分号分隔 + 等号语法是硬性要求,空格会彻底失效
Chrome 100+ 已完全废弃旧版空格分隔语法。写成 allow="microphone geolocation" 或 allow="microphone 'self' geolocation 'self'",整个 allow 字符串会被浏览器忽略,退回到默认全禁状态。
正确格式必须满足三项:每个特性后跟 =、来源列表用括号包裹、多个特性用分号 ; 分隔。漏掉任一符号,策略即失效。
- ✅ 正确:
allow="microphone=(); geolocation='self'; clipboard-read='self'" - ❌ 错误:
allow="microphone 'self'; geolocation 'self'"(缺等号) - ❌ 错误:
allow="microphone=() geolocation=('self')"(空格代替分号) - ⚠️ 注意:
'none'是 Feature-Policy 旧语法,现代浏览器直接忽略整条策略
‘self’ 指 iframe 自身源,和父页面完全无关
嵌入第三方内容时,常误以为 'self' 表示“和父页面同源”。实际它指 iframe src 的协议+域名+端口,与父页面 origin 无任何关系。跨域 iframe 即使加了 'self',也无法读取父页面 DOM,但可基于自身源申请权限。
典型翻车场景:嵌入 https://widget.thirdparty.com/embed,想让它能读剪切板 → 必须写 clipboard-read='https://widget.thirdparty.com' 或 clipboard-read='self',写成 clipboard-read='https://your-site.com' 无效。
- 来源列表对
clipboard-read、payment等生效,但对fullscreen无效(它只看allowfullscreen属性) -
*允许任意来源 → 对microphone或camera使用等于主动交出麦克风/摄像头控制权 - 本地开发用
file://打开 HTML 时,所有allow策略均不生效,必须走 HTTP 服务
验证是否生效不能只看 console,要查 DevTools 权限面板
在 Console 里执行 navigator.permissions.query({ name: 'microphone' }) 返回 state: "prompt",不代表策略已放行——它只说明“尚未被用户拒绝”,真正调用 getUserMedia({ audio: true }) 仍可能因 allow 缺失而失败。
最可靠验证方式是打开 Chrome DevTools → Application → Permissions → 查看对应 API 的状态栏。若显示 “Blocked by feature policy”,说明 allow 未覆盖该特性;若显示 “Prompt” 但调用报错,大概率是来源不匹配或语法错误。
- 调试时建议先用最小化 iframe:
<iframe src="about:blank" allow="microphone=('self')"></iframe> - 不要依赖
document.querySelector('iframe').allow = '...'→allow是 HTML 初始化属性,JS 动态修改无效,必须 reload -
allow优先级高于Permissions-PolicyHTTP 响应头,但只作用于当前 iframe 及其子上下文

















