设备属性 API

社区组报告草案,

此版本:
https://wicg.github.io/WebApiDevice/device_attributes
问题跟踪:
GitHub
编辑:
(Google LLC)

摘要

本文档定义了一个 Web 平台 API,使开发者能够从受管理设备查询设备信息(设备 ID、 序列号、位置等)。这个 API 对虚拟桌面基础设施 (VDI) 和基于上下文的配置等用例非常有价值。

本文档状态

本规范由 Web Platform Incubator Community Group 发布。 它不是 W3C 标准,也不在 W3C 标准轨道上。 请注意,根据 W3C Community Contributor License Agreement (CLA) 存在有限的退出选择,并适用其他条件。 了解更多关于 W3C Community and Business Groups 的信息。

1. 引言

设备属性 API 允许 设备管理员 允许某些源访问运行 UA 的设备的某些 属性。不同于 [MANAGED-CONFIG],后者允许 设备管理员 向每个源传递一个 自定义 JSON 对象,此 API 期望向管理员已启用的所有源传递同一组值。

2. 模型

2.1. 受管理设备

此 API 被认为用于并非完全由最终用户控制,而是由外部实体,即 设备 管理员 控制的设备上。设备管理员 被赋予完全控制这些 受管理设备的能力。

2.2. 受管理 Web 应用

此 API 被认为由 Web 应用使用,这些 Web 应用由 设备 管理员 理解并管理。

2.3. 权限控制

设备属性 API 是一个 强大特性,由 名称 "device-attributes" 标识。

大多数操作系统都有一种用于部署策略的机制,可用于配置设备操作系统或应用程序(例如 Web 浏览器)的许多 方面。本规范要求通过这样的系统来配置访问这些设备属性的 权限。这些策略由 设备 管理员 控制。它们不一定以设备用户的最佳利益为出发点。

以 Chrome 浏览器为例,受管理 Web 应用的状态会授予那些 对应于由 设备管理员Google 管理控制台 中选择的 Web 应用的源,并且这些应用会被自动 安装在企业受管理设备上。对于受管理 Web 应用,如果 设备管理员 不想向某个特定 应用提供访问权限,则可以撤销其访问这些 设备属性的权限。

2.4. 权限策略

本规范定义了一个 由策略控制的特性,由标记字符串 "device-attributes" 标识。

2.5. 设备属性

此 API 被认为与一种管理基础设施一起使用,该基础设施允许 设备管理员 管理一组 设备,并为这些设备配置属性。

2.5.1. 标注的资产 ID

由管理员定义的值,用于在组织内唯一标识设备。

2.5.2. 标注的位置

由管理员定义的值,用于在组织内唯一标识位置。

2.5.3. 目录 ID

由库存管理系统定义的值,用于在组织内唯一标识设备。

2.5.4. 主机名

由管理员定义的值,在 DHCP 请求期间用作设备主机名。

2.5.5. 序列号

由制造商定义的值,用于在该制造商生产的设备中唯一标识一台设备。

[
  SecureContext,
  Exposed=Window
] interface NavigatorManagedData : EventTarget {
  // 设备属性 API。
  Promise<DOMString> getAnnotatedAssetId();
  Promise<DOMString> getAnnotatedLocation();
  Promise<DOMString> getDirectoryId();
  Promise<DOMString> getHostname();
  Promise<DOMString> getSerialNumber();
};

此接口上的方法通常异步完成,会在 受管理数据任务源 上排队工作。

3.1. getAnnotatedAssetId() 方法

getAnnotatedAssetId() 方法步骤 如下:

  1. promise一个新的 promise

  2. 并行运行以下步骤:

    1. 如果此 API 不是由具有访问设备 属性权限的受管理 Web 应用调用,则在 this相关全局对象 上,使用 受管理数据任务 源排队一个全局任务,以用 "NotAllowedError" DOMException 拒绝 promise,并中止这些步骤。

    2. annotatedAssetId设备管理员 设置的 标注的资产 ID,如果尚未设置,则为 undefined

    3. this相关全局对象 上,使用 受管理数据任务源排队一个全局任务,以用 annotatedAssetId 解决 promise

  3. 返回 promise

3.2. getAnnotatedLocation() 方法

getAnnotatedLocation() 方法 步骤如下:

  1. promise一个新的 promise

  2. 并行运行以下步骤:

    1. 如果此 API 不是由具有访问设备 属性权限的受管理 Web 应用调用,则在 this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 "NotAllowedError" DOMException 拒绝 promise,并中止这些步骤。

    2. annotatedLocation设备管理员 设置的 标注的位置,如果尚未设置,则为 undefined

    3. this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 annotatedLocation 解决 promise

  3. 返回 promise

3.3. getDirectoryId() 方法

getDirectoryId() 方法步骤如下:

  1. promise一个新的 promise

  2. 并行运行以下步骤:

    1. 如果此 API 不是由具有访问设备 属性权限的受管理 Web 应用调用,则在 this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 "NotAllowedError" DOMException 拒绝 promise,并中止这些步骤。

    2. directoryId目录 ID,如果管理基础设施未提供,则为 undefined

    3. this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 directoryId 解决 promise

  3. 返回 promise

3.4. getHostname() 方法

getHostname() 方法步骤如下:

  1. promise一个新的 promise

  2. 并行运行以下步骤:

    1. 如果此 API 不是由具有访问设备 属性权限的受管理 Web 应用调用,则在 this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 "NotAllowedError" DOMException 拒绝 promise,并中止这些步骤。

    2. hostname设备 管理员 设置的 主机名,如果尚未设置,则为 undefined

    3. this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 hostname 解决 promise

  3. 返回 promise

3.5. getSerialNumber() 方法

getSerialNumber() 方法步骤如下:

  1. promise一个新的 promise

  2. 并行运行以下步骤:

    1. 如果此 API 不是由具有访问设备 属性权限的受管理 Web 应用调用,则在 this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 "NotAllowedError" DOMException 拒绝 promise,并中止这些步骤。

    2. serialNumber序列号,如果不可用,则为 undefined

    3. this相关全局对象 上,使用 受管理数据 任务源排队一个全局任务,以用 serialNumber 解决 promise

  3. 返回 promise

4. 代码示例

假设有一家依赖在线销售系统的零售企业。后端服务会在早晨根据店内设备的标注位置(国家、城市或销售区域) 向这些设备推送不同资费,并在下午收集销售报告。

借助设备属性 API,这个销售应用可以使用 getAnnotatedLocation() 方法获取设备位置。如果 API 调用是由钓鱼应用触发的,即看起来相似但 并非预期应用,则该操作会失败。

// 如果当前环境有效,则请求敏感数据。
function successCallback(location) {
  const tariff = backend.requestTariff(location);
  console.log(tariff);
}
 
// 如果当前环境不符合预期,则停止工作流。
function failureCallback(error) {
  backend.reportFailure(error);
  console.error(error.message);
}
 
function PrepareTariff() {
  navigator.managed.getAnnotatedLocation()
                   .then(successCallback, failureCallback);
}

很容易再编写另一个类似的代码片段,通过使用 getAnnotatedAssetId() 方法来报告包含设备序列号的销售数据。

注: 网站应当假定这些数据可能被 篡改、窃取或在另一台受管理设备上重用。替代性的安全措施应由网站自身 落实。

function ReportSalesData() {
  navigator.managed.getAnnotatedAssetId.then(reportCallback);
}

5. 安全考虑

按照现代安全实践,使用这些方法的权限由 设备 管理员 按源控制。此外,它们仅在受管理设备上的 安全上下文 中可用。

6. 隐私考虑

此 API 提供对设备属性的访问,这些属性对所有源都是相同的。(关于受管理站点的 按源配置,请参见 [MANAGED-CONFIG]。)如果被任意暴露,这很容易用于跟踪 目的。然而,在受管理环境中,设备管理员 会为特定员工或任务配置一组机器, 因而这些机器能够向其预期访问的站点标识自身是可取的。

此接口的非目标是在非受管理设备上使用。永远不会要求最终用户向站点提供 此信息。哪些源被授予访问这些设备 属性的权限,由其所属组织的授权管理员决定。

为防止不必要的信息暴露,配置机制要求 设备管理员 只向 有限的一组源授予对这些属性的访问权限,因为向所有源授予访问权限会创建一种 可对该设备上的所有 Web 浏览进行普遍跟踪的机制。被授予访问权限的源还必须是 安全上下文,这样被动网络攻击者就无法观察到 这些属性在传输中的内容。

注: [RFC7258] 将普遍监控视为一种攻击,但它 不适用于受管理设备。在此类情况下,受管理设备的实际所有者不是最终用户,而是 设备 管理员,后者应使用适当的权限来保护所有最终用户。

一致性

文档 约定

一致性要求通过描述性断言 和 RFC 2119 术语的组合来表达。 本文档规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应按 RFC 2119 中的说明解释。 但为了可读性, 这些词在本规范中并不总是以全大写字母出现。

除明确标记为非规范性的章节、示例和注释外, 本规范的全部文本均为规范性内容。[RFC2119]

本规范中的示例以 “for example” 这些词引入, 或通过 class="example" 与规范性文本区分开来, 如下所示:

这是一个资料性示例的例子。

资料性注释以 “Note” 一词开头, 并通过 class="note" 与规范性文本区分开来, 如下所示:

注意,这是一个资料性注释。

索引

本规范定义的术语

由引用 定义的术语

引用

规范性引用

[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 标准. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[PERMISSIONS]
Marcos Caceres; Mike Taylor. 权限. URL: https://w3c.github.io/permissions/
[PERMISSIONS-POLICY-1]
Ian Clelland. 权限 策略. URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. 用于在 RFC 中 指示要求级别的关键词. 1997年3月. 最佳当前实践. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行 标准. URL: https://webidl.spec.whatwg.org/

资料性引用

[MANAGED-CONFIG]
Anatoliy Potapchuk. MANAGED-CONFIG. URL: https://wicg.github.io/WebApiDevice/managed_config
[RFC7258]
S. Farrell; H. Tschofenig. 普遍监控是一种 攻击. 2014年5月. 最佳当前实践. URL: https://www.rfc-editor.org/rfc/rfc7258

IDL 索引

[
  SecureContext,
  Exposed=Window
] interface NavigatorManagedData : EventTarget {
  // 设备属性 API。
  Promise<DOMString> getAnnotatedAssetId();
  Promise<DOMString> getAnnotatedLocation();
  Promise<DOMString> getDirectoryId();
  Promise<DOMString> getHostname();
  Promise<DOMString> getSerialNumber();
};