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 | 允许 |
usb | USB 设备 | 允许 |
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>注意事项
- ** Permissions Policy 是白名单机制**:未明确允许的功能将使用默认行为
- 头声明优先级高于 iframe allow:HTTP 头设置可以覆盖 iframe 的 allow
- 向后兼容:旧浏览器不支持 Permissions Policy 时会忽略该头
- 结合 CSP 使用:Permissions Policy 和 CSP 配合提供完整的安全保护
最佳实践
- 对不需要的功能设置
=()禁用 - 对需要的功能限制到特定源
- 禁用广告跟踪:
interest-cohort=() - 在 iframe 中使用
allow属性按需授权 - 检测权限状态提供友好提示
- 测试不同浏览器的支持情况
- 定期审查和更新权限策略
下一节
继续学习:Cross-Origin 策略