Skip to content

Permissions Policy

Permissions Policy(权限策略,原名 Feature Policy)允许网站控制浏览器功能和 API 的使用权限。通过 HTTP 响应头或 <iframe>allow 属性,可以精确控制摄像头、麦克风、地理位置、全屏等浏览器功能的访问权限。本节将介绍 Permissions-Policy header 的配置方法和各种特性的控制策略。

前置知识

阅读本节前,建议先了解:子资源完整性(SRI)

Permissions Policy 概述

Permissions Policy 通过白名单机制控制浏览器功能的使用:

Permissions-Policy: 特性=允许的源

HTTP Header 配置

基本语法

Permissions-Policy: camera=(), microphone=(), geolocation=()

# 允许特定来源
Permissions-Policy: camera=(self "https://trusted.example.com")

# 允许所有
Permissions-Policy: fullscreen=*

# 允许特定来源和 iframe
Permissions-Policy: geolocation=(self "https://maps.example.com")

常用特性

特性说明默认
camera摄像头允许
microphone麦克风允许
geolocation地理位置允许
fullscreen全屏允许
autoplay自动播放允许
payment支付请求 API允许
usbUSB 设备允许
magnetometer磁力计允许
gyroscope陀螺仪允许
accelerometer加速度计允许
encrypted-media加密媒体允许
picture-in-picture画中画允许
clipboard-write写入剪贴板允许
interest-cohort广告跟踪(FLoC)允许

iframe allow 属性

html
<!-- 允许 iframe 使用特定功能 -->
<iframe
  src="https://video.example.com/embed"
  allow="camera; microphone; fullscreen"
  allowfullscreen
></iframe>

<!-- 多功能权限 -->
<iframe
  src="https://maps.example.com/embed"
  allow="geolocation; fullscreen"
  allowfullscreen
></iframe>

<!-- 使用 * 允许所有来源 -->
<iframe
  src="https://partner.example.com/widget"
  allow="camera *"
></iframe>

完整配置示例

严格策略

Permissions-Policy:
  camera=(),
  microphone=(),
  geolocation=(self),
  fullscreen=(self),
  autoplay=(),
  payment=(),
  usb=(),
  interest-cohort=(),
  clipboard-write=(self);

禁用广告跟踪

Permissions-Policy: interest-cohort=()

允许特定域名的地理位置

Permissions-Policy: geolocation=(self "https://maps.example.com")

HTML 中的声明

html
<!-- 通过 meta 标签声明(有限支持) -->
<!-- 注意:仅部分特性支持 meta 声明 -->
<meta name="permissions-policy" content="camera=(), microphone=()">

<!-- 通过 iframe allow 属性 -->
<iframe
  src="https://partner.example.com/widget"
  allow="camera https://partner.example.com; microphone https://partner.example.com"
></iframe>

检测权限状态

javascript
// 检测特定功能是否可用
const cameraStatus = navigator.permissions.query({ name: 'camera' });

cameraStatus.then(result => {
  if (result.state === 'granted') {
    console.log('摄像头权限已授予');
  } else if (result.state === 'denied') {
    console.log('摄像头权限被拒绝');
  } else {
    console.log('摄像头权限待定');
  }
});

// 检测功能是否被 Permissions Policy 阻止
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  try {
    // 尝试请求权限
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
  } catch (error) {
    if (error.name === 'NotAllowedError') {
      console.log('用户拒绝了摄像头权限');
    } else if (error.name === 'NotFoundError') {
      console.log('未找到摄像头设备');
    }
  }
}

实战示例

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Permissions Policy 示例</title>

  <!-- 服务器响应头应设置 -->
  <!-- Permissions-Policy: camera=(self), microphone=(self), geolocation=(self), fullscreen=* -->
</head>
<body>
  <h1>功能权限管理</h1>

  <!-- 带有权限控制的 iframe -->
  <iframe
    src="https://video.example.com/embed/video123"
    sandbox="allow-scripts"
    allow="camera; microphone; fullscreen; autoplay"
    allowfullscreen
    width="640"
    height="360"
    title="视频嵌入"
    referrerpolicy="no-referrer"
  ></iframe>

  <!-- 请求地理位置 -->
  <button onclick="getLocation()">获取位置</button>
  <div id="location-result"></div>

  <script>
    async function getLocation() {
      try {
        const position = await navigator.geolocation.getCurrentPosition(
          (pos) => {
            document.getElementById('location-result').textContent =
              `纬度: ${pos.coords.latitude}, 经度: ${pos.coords.longitude}`;
          },
          (err) => {
            document.getElementById('location-result').textContent =
              `获取位置失败: ${err.message}`;
          }
        );
      } catch (error) {
        document.getElementById('location-result').textContent =
          `地理位置功能不可用`;
      }
    }
  </script>
</body>
</html>

注意事项

  1. ** Permissions Policy 是白名单机制**:未明确允许的功能将使用默认行为
  2. 头声明优先级高于 iframe allow:HTTP 头设置可以覆盖 iframe 的 allow
  3. 向后兼容:旧浏览器不支持 Permissions Policy 时会忽略该头
  4. 结合 CSP 使用:Permissions Policy 和 CSP 配合提供完整的安全保护

最佳实践

  • 对不需要的功能设置 =() 禁用
  • 对需要的功能限制到特定源
  • 禁用广告跟踪:interest-cohort=()
  • 在 iframe 中使用 allow 属性按需授权
  • 检测权限状态提供友好提示
  • 测试不同浏览器的支持情况
  • 定期审查和更新权限策略

下一节

继续学习:Cross-Origin 策略

参考链接