Copyright © 2024 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范定义了其他规范可以用来与浏览器权限交互的通用基础设施。这些权限代表用户对平台“强大功能”访问的允许或拒绝选择。对于开发人员来说,本规范标准化了一个API,用于查询强大功能的权限状态,并在使用强大功能的权限状态发生变化时接收通知。
本节描述了本文档在发布时的状态。当前W3C出版物列表及本技术报告的最新修订版本可在W3C技术报告索引中找到,网址为:https://www.w3.org/TR/。
本文档正在开发中。
本文档由 Web 应用程序安全工作组 作为工作草案发布, 采用推荐标准流程。
作为工作草案发布并不意味着W3C及其成员的认可。
本文档是草稿,可能随时被更新、替换或废弃。引用本文档时只能作为工作进展的参考。
本文档由一个在 W3C 专利政策下运作的团体制定。 W3C 维护一个 与该团体交付成果相关的任何专利披露的公开列表; 该页面还包含披露专利的说明。任何实际知晓某项专利,并认为该专利包含 必要权利要求的个人, 必须根据 W3C 专利政策第 6 节披露该信息。
本文档受 2023年11月3日 W3C 流程文档的约束。
本节为非规范性内容。
规范可以定义被明确标识为强大功能的特性。这些特性之所以被称为“强大”,是因为它们可能对隐私、安全性和性能产生重大影响。因此,用户依赖用户代理来拒绝网站使用这些特性,直到用户明确授予权限,并且通常仅限于授予一段有限的时间。允许网站使用强大功能的明确权限通常通过浏览器UI来授予和控制,如下图所示。
从这个意义上说,权限表示用户对某些类型功能,尤其是“强大功能”的当前同意状态。最终,用户保留这些权限的控制权,并有能力通过用户偏好手动授予或拒绝权限。此外,用户代理帮助用户管理权限,例如,隐藏和自动拒绝某些可能造成麻烦的权限提示,并在用户长时间未访问某个网站时自动使已授予的权限过期。
本节为非规范性内容。
本示例使用权限API决定是否通过地理位置API显示本地新闻,或提供一个按钮以添加该功能。
const { state } = await navigator.permissions.query({
name: "geolocation"
});
switch (state) {
case "granted":
showLocalNewsWithGeolocation();
break;
case "prompt":
showButtonToEnableLocalNews();
break;
case "denied":
showNationalNews();
break;
}
本示例同时检查"geolocation"
和"notifications"
强大功能的状态:
const queryPromises = ["geolocation", "notifications"].map(
name => navigator.permissions.query({ name })
);
for await (const status of queryPromises) {
console.log(`${status.name}: ${status.state}`);
}
本示例正在检查可用摄像头的权限状态。
const devices = await navigator.mediaDevices.enumerateDevices();
// filter on video inputs, and map to query object
const queries = devices
.filter(({ kind }) => kind === "videoinput")
.map(({ deviceId }) => ({ name: "camera", deviceId }));
const promises = queries.map((queryObj) =>
navigator.permissions.query(queryObj)
);
try {
const results = await Promise.all(promises);
// log the state of each camera
results.forEach(({ state }, i) => console.log("Camera", i, state));
} catch (error) {
console.error(error);
}
权限表示用户允许Web应用程序使用强大功能的决策。该决策以权限状态表示。
为了获取用户意图的新信息,用户代理可以收集并解释用户意图的信息。这些信息可以来自用户的明确操作、相关用户和其他用户的汇总行为,或本文档未预见的隐式信号。
每个权限都有一个生命周期, 指的是特定权限在恢复到其默认状态之前保持“授予”状态的持续时间。一个生命周期 可能持续到特定的领域 (Realm) 被销毁,直到特定的 顶级浏览上下文被销毁,一段特定的时间,或者是无限的。 当用户通过权限用户界面或用户代理定义的策略授予使用某个功能的明确许可时,生命周期由最终用户和用户代理协商确定。
用户代理维护一个单一的权限存储,它是一个权限存储条目的列表。每个由其描述符和键表示的特定条目在此列表中最多只能出现一次。
当相应权限的生命周期已过期时,用户代理可以从权限存储中移除条目。
一个权限存储条目是一个由PermissionDescriptor
描述符、权限键 键和状态 状态组成的元组。
给定一个PermissionDescriptor
描述符和一个权限键
键,要获取权限存储条目:
给定一个PermissionDescriptor
描述符、一个权限键
键
和一个状态 状态,要设置权限存储条目,请执行以下步骤:
权限键的类型由功能的权限键类型定义。
强大功能是指用户在使用前需要给予明确许可的 Web 平台功能(通常是 API)。 除少数显著例外(例如,通知 API 标准),大多数强大功能也是策略控制的功能。对于同时也是策略控制的功能的强大功能,[权限策略] 控制文档是否允许使用给定的功能。 也就是说,只有当文档通过相应的策略控制的功能获得了权限委派时,强大功能才能向用户请求明确许可(参见下面的示例)。 后续对该功能的访问取决于用户是否已“授予”权限,或者满足某些等同于权限授予的标准。
强大功能由其名称标识,该名称是一个字符串字面量(例如,“geolocation”)。
用户代理通过环境设置对象跟踪用户拥有使用哪些强大功能的权限。
每个强大功能可以定义零个或多个额外的方面。方面定义为 WebIDL
字典,它继承自 PermissionDescriptor
并用作 WebIDL
接口的权限描述符类型。
当符合规范指定强大功能时,它:
PermissionDescriptor
。
在权限注册表中注册新指定的强大功能,为该工作组提供了反馈机会,并检查与本规范的集成是否有效。
PermissionDescriptor
或其子类型。如果未指定,默认值为PermissionDescriptor
。
该功能可以定义描述符实例的部分顺序。如果descriptorA强于descriptorB,则如果descriptorA的权限状态为"granted
",则descriptorB的权限状态也必须为"granted
",如果descriptorB的权限状态为"denied
",则descriptorA的权限状态也必须为"denied
"。
某些强大功能比仅仅提供一个PermissionState
关联了更多信息。这些功能中的每一个都定义了一个额外权限数据类型。
例如,getUserMedia
()
需要确定用户已授予访问权限的哪些摄像头。
如果指定,则该额外权限数据算法可用于此功能。
PermissionStatus
或其子类型。如果未指定,默认值为PermissionStatus
。
接收一个权限描述符类型实例和一个新的或现有的权限结果类型实例,并更新权限结果类型实例的查询结果。由Permissions
的query
(permissionDesc)
方法和PermissionStatus
更新步骤使用。如果未指定,默认使用默认权限查询算法。
默认权限查询算法,给定一个PermissionDescriptor
permissionDesc和一个PermissionStatus
status,运行以下步骤:
该功能使用的权限密钥的类型。默认为源 (origin)。指定自定义权限密钥类型的功能必须同时指定一个权限密钥生成算法。
接受一个环境设置对象,并返回一个新的权限密钥。如果未指定,则默认为默认权限密钥生成算法。 指定自定义权限密钥生成算法的功能必须同时指定一个权限密钥比较算法。
接受两个权限密钥并返回一个布尔值,该布尔值显示两个密钥是否相等。如果未指定,则默认为默认权限密钥比较算法。
不接收任何参数。更新实现中的其他部分,使其与权限状态或额外权限数据的变化保持同步。
如果未指定,默认运行响应用户撤销权限。
定义一个或多个强大功能的规范应该建议最适合特定功能的权限生命周期。 以下提供了一些确定权限生命周期的指南,重点是用户隐私。如果未指定生命周期,则由用户代理提供。
当来源的权限生命周期到期时:
一个PermissionState
值,用作权限的默认状态,适用于强大功能。
要获取当前权限状态,给定一个名称 name 和一个可选的环境设置对象
settings,请运行以下步骤。此算法返回一个 PermissionState
枚举值。
PermissionDescriptor
,其
name
被初始化为
name。
一个 描述符的权限状态,给定一个可选的环境设置对象
settings,是以下算法的结果。
它返回一个 PermissionState
枚举值:
denied
”。
name
。
Document
,则运行以下步骤:
Document
。
denied
”。
PermissionState
枚举值。
PermissionState
枚举值,同时考虑 描述符的name
的任何权限状态约束。
作为简写,一个 DOMString
name的权限状态是权限状态,其PermissionDescriptor
的name
成员设置为name。
要请求使用权限一个描述符,用户代理必须执行以下步骤。
该算法返回"granted
"或"denied
"。
prompt
",
返回current state并中止这些步骤。
granted
”;
否则设置为“denied
”。
用户的交互可能会为源提供关于用户意图的新信息。
此处故意对权限用户界面的细节以及用户代理如何推断用户意图保持模糊。用户代理应该能够在此框架内探索许多用户界面。
作为简写,请求使用权限一个DOMString
name,与请求使用权限一个PermissionDescriptor
(其name
成员设置为name)相同。
要提示用户选择与给定描述符关联的一个或多个选项,以及一个可选的布尔值
allowMultiple(默认为 false),用户代理必须执行以下步骤。此算法返回“denied
”或用户的选择。
denied
",
则返回"denied
"并中止这些步骤。
granted
",用户代理可以返回用户选择的一个(或多个,如果
allowMultiple为true)选项,并中止这些步骤。如果用户代理在不提示的情况下返回,
则后续对相同描述符和相同选项集的提示必须返回相同的选项,
除非用户代理收到了有关用户意图的新信息。
denied
"。
该操作故意对权限UI的细节以及用户代理如何推断用户意图保持模糊。用户代理应能够在此框架内探索大量UI选项 (例如,权限提示可能会超时并自动返回"denied",而无需用户明确选择)。
作为简写,提示用户从与DOMString
name 关联的选项中进行选择,等同于提示用户从与PermissionDescriptor
(其 name
成员设置为
name)关联的那些选项中进行选择。
当用户代理得知用户不再打算授予使用描述符中描述的功能的权限,并且该功能是在由
PermissionDescriptor
中的key描述的上下文中时,通过执行以下步骤对用户撤销权限的操作:
WebIDL[Exposed=(Window,Worker)]
interface Permissions
{
Promise<PermissionStatus
> query
(object permissionDesc);
};
dictionary PermissionDescriptor
{
required DOMString name
;
};
当调用 query()
方法时,用户代理 必须运行以下查询权限算法,并传递参数
permissionDesc:
Window
对象,则:
Document
不是完全激活状态,则返回一个被拒绝的
promise,并带有一个“InvalidStateError
”
DOMException
。
PermissionDescriptor
。
name
"]
不受支持,则返回一个被拒绝的 promise,并带有一个 TypeError
。
name
的权限描述符类型。
WebIDL[Exposed=(Window,Worker)]
interface PermissionStatus
: EventTarget {
readonly attribute PermissionState
state
;
readonly attribute DOMString name
;
attribute EventHandler onchange
;
};
enum PermissionState
{
"granted
",
"denied
",
"prompt
",
};
PermissionStatus
实例会创建一个
[[query]] 内部槽,
它是某个特性的 权限描述符类型 的实例。
"granted
"、"denied
" 和
"prompt
" 枚举值分别表示 "授予"、"拒绝" 和
"提示" 的概念。
name
属性返回其初始化的值。
state
属性返回在当前实例上设置的最新值。
onchange
属性是一个事件处理程序,其对应的事件处理程序事件类型是
change
。
每当用户代理意识到 PermissionStatus
实例 status 的状态发生更改时,它会异步运行PermissionStatus
更新步骤:
如果一个 PermissionStatus
对象具有一个类型为 change
的事件侦听器,则该对象不得被垃圾回收。
除了标记为非规范的部分外,本规范中的所有创作指南、图表、示例和注释均为非规范内容。本规范中的其他内容均为规范性内容。
本文件中的关键词 MAY、MUST、MUST NOT、OPTIONAL 和 SHOULD 应按照 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释,仅当它们以全大写形式出现时,如本处所示。
本节为非规范性内容。
尽管本规范与 权限策略 规范都涉及“权限”,但每个规范在平台中都有独特的作用。 尽管如此,这两个规范确实存在明确的重叠。
一方面,本规范只关心通过用户代理权限UI管理访问的 强大功能 (即,用户在使用该功能前给予明确同意,并且用户可以随时以任何理由拒绝该权限的权限),这些强大功能已在 权限注册表 中注册。
另一方面,权限策略规范允许开发人员通过“权限策略”(无论是
HTTP 标头还是
allow
属性)选择性地启用和禁用策略控制的功能。从这个意义上说,权限策略包含了本规范,因为权限策略独立于本规范来决定某个功能是否可用。这些策略控制的功能也注册在权限注册表中。
一个被权限策略规范禁用的强大功能,其权限状态在本规范中始终反映为“拒绝”。 这是因为读取当前权限依赖于[HTML]的“允许使用”检查,而该检查本身会调用权限策略规范。 此处需要注意的重要一点是两个规范之间共享权限名称。本规范和权限策略规范都依赖于其他规范来定义权限的名称和名称,并且它们通常被命名为相同的东西(例如,地理位置的“geolocation”,等等)。
最后,通过 权限策略 规范,强大功能永远不可能被授予“granted”状态。 强大功能被 “授予” 的唯一方法是通过用户明确的权限或某些用户代理策略。
为了用户代理自动化和应用程序测试的目的,本文档定义了对 [WebDriver] 和 [WebDriver-BiDi] 规范的扩展。用户代理支持它们是可选的。
WebIDLdictionary PermissionSetParameters
{
required object descriptor
;
required PermissionState
state
;
};
为给定的 PermissionDescriptor
descriptor、PermissionState
state、一个可选的 origin 和一个可选的
user agent 设置权限时:
HTTP 方法 | URI 模板 |
---|---|
POST | /session/{session id}/permissions |
设置权限扩展命令模拟用户修改 PermissionDescriptor
的权限状态。
远程端步骤如下:
PermissionSetParameters
。如果此操作抛出异常,则返回无效参数错误。
state
是一个不适当的权限状态,则返回无效参数错误。
descriptor
。
name
") 结果匹配的权限描述符类型。如果此操作抛出异常,则返回无效参数错误。
state
设置权限。
null
。
本文档为 [WebDriver-BiDi] 规范定义了以下扩展模块。
权限模块包含管理远程端浏览器权限的命令。
PermissionsCommand = (
permissions.setPermission
)
permissions.PermissionDescriptor = {
name: text,
}
permissions.PermissionDescriptor
类型表示 PermissionDescriptor
。
permissions.PermissionState = "granted" / "denied" / "prompt"
permissions.PermissionState
类型表示 PermissionState
。
设置权限命令模拟用户修改 PermissionDescriptor
的权限状态。
permissions.setPermission = (
method: "permissions.setPermission",
params: permissions.SetPermissionParameters
)
permissions.SetPermissionParameters = {
descriptor: permissions.PermissionDescriptor,
state: permissions.PermissionState,
origin: text,
? userContext: text,
}
EmptyResult
使用 session 和 command parameters 的远程端步骤如下:
descriptor
字段的值。
name
字段的值,代表 name
。
state
字段的值。
userContext
字段的值(如果存在),否则为 default
。
PermissionSetParameters
permission
name 的权限描述符类型。如果此转换引发异常,则返回带有错误代码 invalid
argument 的错误。
origin
字段的值。
null
的成功。
本节为非规范性内容。
这个 W3C 注册表提供了一个集中的位置,用于查找 Web 平台的策略控制功能和/或强大功能。通过变更过程,它还有助于确保平台中的权限在各种规范中得到一致的指定。
通过将注册表划分为标准化权限和临时权限,注册表还提供了一种方法来跟踪这些功能的状态。
本更改过程 用于添加或更新此注册表,步骤如下:
要使某个权限出现在标准化权限表中,并被认为是 标准化权限,需要满足以下标准:
每个权限都由一个唯一的文字字符串标识。对于权限策略,该字符串标识一个策略控制的功能。 类似地,在权限规范中,该字符串标识一个强大功能。
标识字符串 | 是策略控制的功能吗? | 是强大功能吗? | 规范 | 实现 | ||
---|---|---|---|---|---|---|
Chromium | Gecko | WebKit | ||||
"geolocation" | 是 | 是 | Geolocation | 是 | 是 | 是 |
"notifications" | 否 | 是 | Notifications API Standard | 是 | 是 | 是 |
"push" | 否 | 是 | Push API | 是 | 是 | 是 |
"web-share" | 是 | 否 | Web Share API | 是 | 是 | 是 |
临时权限是尚未 标准化 的权限 (即它们要么是实验性的,还处于孵化阶段,或者仅在单一浏览器引擎中实现)。
标识字符串 | 是策略控制的功能吗? | 是强大功能吗? | 规范 | 实现 | ||
---|---|---|---|---|---|---|
Chromium | Gecko | WebKit | ||||
"accelerometer" | 是 | 是 | 设备方向和运动 | 是 | 否 | 否 |
"window-management" | 是 | 是 | 窗口管理 | 是 | 否 | 否 |
"local-fonts" | 是 | 是 | 本地字体访问 | 是 | 否 | 否 |
对手可能会利用权限状态作为创建用户“指纹”的元素。虽然对手已经可以通过实际使用 API 来确定权限状态,但这通常会导致向终端用户显示 UI 提示(如果权限尚未被“授予”)。虽然该 API 不会向网站暴露新的指纹信息,但它使对手更容易悄悄地访问这些信息。
目前没有记录的安全注意事项。建议读者参考第D. 隐私注意事项部分。
WebIDL[Exposed=(Window)]
partial interface Navigator {
[SameObject] readonly attribute Permissions
permissions
;
};
[Exposed=(Worker)]
partial interface WorkerNavigator {
[SameObject] readonly attribute Permissions
permissions
;
};
[Exposed=(Window,Worker)]
interface Permissions
{
Promise<PermissionStatus
> query
(object permissionDesc);
};
dictionary PermissionDescriptor
{
required DOMString name
;
};
[Exposed=(Window,Worker)]
interface PermissionStatus
: EventTarget {
readonly attribute PermissionState
state
;
readonly attribute DOMString name
;
attribute EventHandler onchange
;
};
enum PermissionState
{
"granted
",
"denied
",
"prompt
",
};
dictionary PermissionSetParameters
{
required object descriptor
;
required PermissionState
state
;
};
本节为非规范性部分。
编辑们感谢 Adrienne Porter Felt、Anne van Kesteren、Domenic Denicola、Jake Archibald 和 Wendy Seltzer 对 API 设计和编辑工作的帮助。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: