唯一标识符最佳做法

本文档提供了有关如何根据您的用例为应用选择适当标识符的指导。

如需大致了解 Android 权限,请参阅权限概览。如需了解使用 Android 权限方面的具体最佳实践,请参阅应用权限最佳实践

使用 Android 标识符的最佳做法

为了保护用户的隐私,请使用符合应用使用情形且限制性最强的标识符。具体而言,请遵循以下最佳实践:

  1. 尽可能选择用户可重置的标识符。即使您的应用使用了不可重置的硬件 ID 以外的标识符,它也能满足其大多数用例。
  2. 避免使用硬件标识符在大多数用例中,您可以避免使用硬件标识符(例如国际移动设备识别码 [IMEI]),而不限制必需的功能。

    Android 10(API 级别 29)针对不可重置的标识符(包括 IMEI 和序列号)添加了限制。如需访问这些标识符,您的应用必须是设备或资料所有者应用,具有特殊运营商权限,或具有 READ_PRIVILEGED_PHONE_STATE 特许权限。

  3. 只针对用户剖析或广告用例使用广告 ID使用广告 ID 时,请始终遵循用户关于广告跟踪的选择。如果您必须将广告标识符与个人身份信息相关联,则只能在用户明确同意的情况下执行此操作。

  4. 请勿桥接广告 ID 重置。

  5. 尽一切可能针对防欺诈支付和电话以外的所有其他用例使用 Firebase 安装 ID (FID) 或私密存储的 GUID。对于绝大多数非广告用例,使用 FID 或 GUID 应该就够了。

  6. 使用适合您的用例的 API 以最大限度地降低隐私权风险。使用 DRM API 保护重要内容,并使用 Play Integrity API 防止滥用行为。Play Integrity API 是确定设备真伪且不会带来隐私风险的最简单方法。

本指南其余部分将以开发 Android 应用为背景详细介绍这些规则。

使用广告 ID

广告 ID 是用户可重置的标识符,适用于广告用例。不过,在使用此 ID 时,请注意以下要点:

始终尊重用户重置广告 ID 的意图。 未经用户同意,请勿使用其他标识符或指纹将后续广告 ID 关联起来,对用户重置进行桥接。Google Play 开发者内容政策声明如下:

“...重置后,在未获得用户明确许可的情况下,新的广告标识符不得与先前的广告标识符或由先前的广告标识符所衍生的数据相关联。”

始终尊重关联的个性化广告标记广告 ID 是可配置的,用户可以限制与 ID 关联的跟踪数量。请务必使用 AdvertisingIdClient.Info.isLimitAdTrackingEnabled() 方法,确保您没有规避用户的意愿。Google Play 开发者内容政策声明如下:

“...您必须遵守用户的‘选择停用针对用户兴趣投放广告’或‘选择停用广告个性化功能’设置。如果用户已启用此设置,您不得出于广告目的使用该广告标识符创建用户个人资料,也不得使用该广告标识符向用户投放个性化广告。允许的活动包括:内容相关广告投放、频次上限、转化跟踪、生成报表,以及安全性和欺诈检测。”

请注意与您使用的 SDK 有关且涉及广告 ID 使用的任何隐私权或安全政策。 例如,如果您将 true 从 Google Analytics(分析)SDK 传入 enableAdvertisingIdCollection() 方法,请务必查看并遵守所有适用的 Google Analytics(分析)SDK 政策

另请注意,Google Play 开发者内容政策规定,广告 ID“不得与个人身份信息或任何永久性设备标识符(例如:SSAID、MAC 地址、IMEI 等)相关联”。

例如,假设您想要收集信息以填充包含以下列的数据库表:

TABLE-01
timestamp ad_id account_id clickid
TABLE-02
account_id name dob country

在本例中,ad_id 列可通过两个表中的 account_id 列与个人身份信息 (PII) 联接,如果您未获得用户的明确许可,就会违反 Google Play 开发者内容政策

请注意,广告客户 ID 与 PII 之间的关联并非总是如此。PII 和广告 ID 键控表中可能都存在“准标识符”,这也会造成问题。例如,假设我们对 TABLE-01 和 TABLE-02 做如下更改:

TABLE-01
timestamp ad_id clickid dev_model
TABLE-02
timestamp demo account_id dev_model name

在这种情况下,如果点击事件足够罕见,您仍然可以使用事件和设备型号在广告客户 ID TABLE-01 与 TABLE-02 中包含的 PII 之间联接。

虽然通常很难保证数据集中不存在此类准标识符,但您可以尽可能泛化唯一数据,以防止最明显的联接风险。在前面的示例中,这意味着会降低时间戳的准确性,以便每个时间戳都显示同一型号的多台设备。

其他解决方案包括:

  • 设计表时不在 PII 与广告 ID 之间建立明确关联在上面的第一个示例中,这意味着 TABLE-01 中不包含 account_id 列。

  • 针对同时有权访问广告 ID 键控数据和个人身份信息的用户或角色,隔离并监控其访问控制列表。 通过严格控制和审核同时访问这两个来源的能力(例如,通过在表之间执行联接),您可以降低广告 ID 与 PII 之间关联的风险。一般来说,控制访问权限意味着执行以下操作:

    1. 确保广告主 ID 键控数据和个人身份信息的访问控制列表 (ACL) 不相交,以尽量减少同时存在于两个 ACL 中的个人或角色的数量。
    2. 实现访问日志记录和审核,以检测和管理此规则的任何例外情况。

如需详细了解如何以负责任的方式使用广告 ID,请参阅 AdvertisingIdClient API 参考文档。

使用 FID 和 GUID

如需识别设备上运行的应用实例,最直接的解决方案就是使用 Firebase 安装 ID (FID),在大多数非广告用例中,这是推荐的解决方案。只有进行了相应配置的应用实例才能访问此标识符,而且标识符(相对)可轻松重置,因为只要应用已安装完毕,它就会存在。

因此,与不可重置的设备级硬件 ID 相比,FID 可提供更好的隐私属性。如需了解详情,请参阅 firebase.installations API 参考文档。

如果 FID 不切实际,您还可以使用自定义全局唯一 ID (GUID) 来唯一标识应用实例。最简单的方法是使用以下代码生成您自己的 GUID:

Kotlin

var uniqueID = UUID.randomUUID().toString()

Java

String uniqueID = UUID.randomUUID().toString();

由于该标识符具有全局唯一性,因此可用于识别特定应用实例。为了避免与跨应用关联标识符有关的问题,请将 GUID 存储在内部存储空间而不是外部(共享)存储空间中。如需了解详情,请参阅数据和文件存储概览页面。

不要使用 MAC 地址

MAC 地址具有全局唯一性,不可由用户重置,在恢复出厂设置后仍然有效。出于这些原因,为了保护用户隐私,在 Android 6 及更高版本上,只有系统应用才能访问 MAC 地址。第三方应用无法访问它们。

Android 11 中的 MAC 地址可用性变更

在以 Android 11 及更高版本为目标平台的应用中,Passpoint 网络随机分配 MAC 地址是按 Passpoint 配置文件进行的,并会根据以下字段生成一个唯一的 MAC 地址:

  • 完全限定域名 (FQDN)
  • 领域
  • 基于 Passpoint 配置文件中使用的凭据的凭据:
    • 用户凭据:用户名
    • 证书凭据:证书和证书类型
    • SIM 凭据:EAP 类型和 IMSI

此外,非特权应用无法访问设备的 MAC 地址;只有具有 IP 地址的网络接口可见。这会影响 getifaddrs()NetworkInterface.getHardwareAddress() 方法,以及 RTM_GETLINK Netlink 消息的发送。

下面列出了此变更会以哪些方式影响应用:

  • NetworkInterface.getHardwareAddress() 会针对每个接口返回 null。
  • 应用无法对 NETLINK_ROUTE 套接字使用 bind() 函数。
  • ip 命令不会返回有关接口的信息。
  • 应用无法发送 RTM_GETLINK 消息。

请注意,大多数开发者应该使用级别较高的 ConnectivityManager API,而不是级别较低的 API(如 NetworkInterfacegetifaddrs() 或 Netlink 套接字)。例如,如果应用需要有关当前路由的最新信息,则可以通过以下方式获取此信息:使用 ConnectivityManager.registerNetworkCallback() 监听网络更改,并调用与网络相关联的 LinkProperties.getRoutes()

标识符特性

Android 操作系统提供了多种具有不同行为特性的 ID。您应该使用哪个 ID 取决于以下特性是否适合您的用例。但是,这些特性还会对隐私保护造成影响,因此了解这些特性之间的相互作用方式非常重要。

范围

标识符作用域说明了哪些系统可以访问标识符。Android 标识符范围通常分为以下三种类型:

  • 单一应用 - ID 仅限应用内部使用,其他应用无法访问。
  • 一组应用 - ID 可供一组预先定义的相关应用访问。
  • 设备 - ID 可供安装在设备上的所有应用访问。

向标识符授予的范围越大,将其用于跟踪目的的风险就越大。相反,如果某个标识符只能由单个应用实例访问,则无法用于跨不同应用的事务跟踪设备。

重置性与持久性

重置性和持久性定义了标识符的生命周期并说明了如何对其进行重置。常见的重置触发器包括:应用内重置、通过系统设置重置、启动时重置以及安装时重置。Android 标识符可能具有不同的生命周期,但生命周期通常与 ID 的重置方式有关:

  • 仅限会话期间 - 每次用户重新启动应用时都使用新的 ID。
  • 安装重置 - 每次用户卸载并重新安装应用时都使用新的 ID。
  • FDR 重置 - 每次用户恢复设备出厂设置时都使用新的 ID。
  • FDR 持久性 - ID 在恢复出厂设置后保持不变。

重置性让用户能够创建与任何现有个人资料信息解除关联的新 ID。标识符的存在时间越长、越可靠(例如在恢复出厂设置后持续存在的标识符),用户被长期跟踪的风险就越高。如果应用重新安装时标识符被重置,那么即使没有明确的用户控件可在应用或系统设置中重置该 ID,这样做也能缩短其持久性并提供一种重置 ID 的方式。

Uniqueness

唯一性决定了发生冲突的可能性,即关联作用域中存在相同标识符。在最高级别,全局唯一标识符永远不会发生冲突,即使在其他设备或应用上也是如此。否则,唯一性级别取决于标识符的熵以及用于创建标识符的随机性来源。例如,带有安装日期种子的随机标识符(例如 2019-03-01)的冲突几率要比带有 Unix 安装时间戳(例如 1551414181)的标识符高得多。

一般而言,您可以将用户账号标识符视为具有唯一性。也就是说,每个设备/帐号组合都有一个唯一 ID。另一方面,标识符在群体中的唯一性越低,隐私保护力度就越大,因为它对跟踪单个用户没什么用。

完整性保护和不可否认性

您可以使用难以伪造或重放的标识符来证明关联的设备或帐号具有某些属性。例如,您可以证明设备并非被垃圾内容发布者使用的虚拟设备。难以仿冒的标识符还能提供不可否认性。如果设备使用密钥对消息进行了签名,就很难声称该消息是由他人的设备发送的。不可否认性可能是用户所希望的(例如,在对付款进行身份验证时),也可能是一个不希望出现的属性(例如,当用户发送了让他们后悔的消息时)。

常见用例和适用的标识符

此部分为使用 IMEI 等硬件 ID 提供了替代方案。不建议使用硬件 ID,因为用户无法重置它们,并且它们的作用域仅限于相应设备。在许多情况下,作用范围仅限于应用的标识符足以满足您的需求。

账号

运营商状态

在此情况下,您的应用会通过运营商帐号与设备的电话和短信功能进行交互。

建议使用的标识符:IMEI、IMSI 和 Line1

为什么这样建议?

如果运营商相关功能要求使用硬件标识符,则可以这样做。例如,您可以使用这些标识符在移动网络运营商或 SIM 卡插槽之间切换,或通过 IP(适用于 Line1)发送短信(基于 SIM 卡的用户帐号)。但是,对于非特权应用,我们建议使用帐号登录在服务器端检索用户设备信息。原因之一是,在 Android 6.0(API 级别 23)及更高版本中,这些标识符只能通过运行时权限使用。用户可能会关闭此权限,因此您的应用应妥善处理这些异常。

移动设备订阅状态

在这种情况下,您需要将应用功能与设备上的某些移动服务订阅相关联。例如,您可能需要根据设备的移动订阅(通过 SIM 卡)验证对某些付费应用功能的访问权限。

建议使用的标识符订阅 ID API 用于标识设备上使用的 SIM 卡。

订阅 ID 提供了一个索引值(从 1 开始),用于对设备上安装的 SIM 卡(包括实体 SIM 卡和电子 SIM 卡)进行唯一标识。通过此 ID,应用可将其功能与给定 SIM 卡的各种订阅信息相关联。对于给定 SIM 卡,该值是稳定的,除非设备恢复出厂设置。不过,可能会存在这样的情况:同一 SIM 卡在不同设备上具有不同的订阅 ID,或者不同 SIM 卡在不同设备上具有相同的 ID。

为什么这样建议?

某些应用目前可能出于此目的使用 ICC ID。由于 ICC ID 具有全局唯一性且不可重置,因此从 Android 10 开始,只有具有 READ_PRIVILEGED_PHONE_STATE 权限的应用才能访问该 ID。从 Android 11 开始,Android 进一步限制了通过 getIccId() API 访问 ICCID,无论应用的目标 API 级别如何。受影响的应用应进行迁移,改用订阅 ID。

单点登录

在这种情况下,您的应用提供单点登录体验,允许用户将现有帐号与您的组织相关联。

建议使用的标识符:与客户经理兼容的账号,例如 Google 账号关联

为什么这样建议?

借助 Google 账号关联功能,用户可以将用户的现有 Google 账号与您的应用相关联,从而更顺畅、更安全地访问贵组织的产品和服务。此外,您还可以定义自定义 OAuth 范围,以仅共享必要的数据,从而通过明确定义数据使用方式来提高用户信任度。

广告

定位条件

在这种情况下,您的应用会建立一份用户兴趣资料,以向用户展示相关性更高的广告。

推荐使用的标识符:如果您的应用使用 ID 展示广告,并将其上传到 Google Play 或发布到 Google Play,则该 ID 必须是广告 ID。

为什么这样建议?

这是一个与广告相关的用例,可能需要一个可用于组织不同应用的 ID,因此使用广告 ID 是最合适的解决方案。根据 Google Play 开发者内容政策,在广告用例中使用广告 ID 是强制性要求,因为用户可以重置广告 ID。

无论您是否在应用中分享用户数据,如果您出于广告目的收集和使用这些数据,都需要在 Play 管理中心应用内容页面的“数据安全”部分中声明广告用途。

测量

在此情况下,您的应用会根据用户在同一设备上组织的所有应用中的行为创建用户的个人资料。

建议使用的标识符:广告 ID 或 Play 安装引荐来源网址 API

为什么这样建议?

这是一个与广告相关的用例,可能需要一个可用于组织不同应用的 ID,因此使用广告 ID 是最合适的解决方案。如果您将某个 ID 用于广告用例,则该 ID 必须是广告 ID,因为用户可以对其进行重置。如需了解详情,请参阅 Google Play 开发者内容政策

转化次数

在这种情况下,您需要跟踪转化情况,以检测您的营销策略是否成功。

建议使用的标识符:广告 ID 或 Play 安装引荐来源网址 API

为什么这样建议?

这是一个与广告相关的用例,可能需要一个可用于组织不同应用的 ID,因此使用广告 ID 是最合适的解决方案。根据 Google Play 开发者内容政策,在广告用例中使用广告 ID 是强制性要求,因为用户可以重置广告 ID。

再营销

在这种情况下,您的应用会根据用户之前的兴趣展示广告。

建议使用的标识符:广告 ID

为什么这样建议?

这是一个与广告相关的用例,可能需要一个可用于组织不同应用的 ID,因此使用广告 ID 是最合适的解决方案。根据 Google Play 开发者内容政策,在广告用例中使用广告 ID 是强制性要求,因为用户可以重置广告 ID。

应用分析工具

在这种情况下,您的应用会评估用户行为,以帮助您确定以下内容:

  • 贵组织的哪些其他产品或应用可能适合该用户。
  • 如何持续激发用户使用应用的兴趣。
  • 衡量已退出登录或匿名用户的使用情况统计信息和分析数据。

可能的解决方法包括:

  • 应用组 ID:只要您不将用户数据用于广告目的,就可以通过应用组 ID 分析用户在贵组织拥有的多个应用中的行为。如果您的目标设备搭载 Google Play 服务,我们建议您使用应用组 ID。
  • Firebase ID (FID):FID 的作用域限定为创建它的应用,这样可防止使用该标识符跨应用跟踪用户。此外,它还可以易于重置,因为用户可以清除应用数据或重新安装应用。FID 的创建过程非常简单;请参阅 Firebase 安装指南。

应用开发

崩溃报告

在此情况下,您的应用会收集有关其在用户设备上崩溃的时间和原因的数据。

建议使用的标识符:FID 或应用组 ID

为什么这样建议?

FID 的作用域限定为创建它的应用,这样可以防止使用该标识符跨应用跟踪用户。它也可以轻松重置,因为用户可以清除应用数据或重新安装应用。创建 FID 的过程很简单;请参阅 Firebase 安装指南。只要您不将用户数据用于广告目的,您就可以通过应用组 ID 分析用户在贵组织拥有的多个应用中的行为。

效果报告

在这种情况下,应用会收集性能指标(例如加载时间和电池用量),以帮助提高应用的质量。

建议使用的标识符Firebase Performance Monitoring

为什么这样建议?

Firebase Performance Monitoring 可帮助您专注于对您最重要的指标,并测试应用中最近更改的影响。

应用测试

在这种情况下,您的应用会出于测试或调试目的评估用户使用应用的体验。

建议使用的标识符:FID 或应用组 ID

为什么这样建议?

FID 的作用域限定为创建它的应用,这样可以防止使用该标识符跨应用跟踪用户。它也可以轻松重置,因为用户可以清除应用数据或重新安装应用。创建 FID 的过程很简单;请参阅 Firebase 安装指南。只要您不将用户数据用于广告目的,您就可以通过应用组 ID 分析用户在贵组织拥有的多个应用中的行为。

跨设备安装

在此情况下,当您的应用安装到同一用户的多台设备上时,您的应用需要识别正确的应用实例。

建议使用的标识符:FID 或 GUID

为什么这样建议?

FID 是专为此目的而设计的;其范围仅限于应用,因此无法用于跟踪用户在不同应用中的行为,并且会在应用重新安装时重置。在 FID 不足的极少数情况下,您还可以使用 GUID。

安全性

滥用行为检测

在此情况下,您希望发现多台正在攻击后端服务的虚假设备。

建议使用的标识符:Google Play Integrity API 完整性令牌

为什么这样建议?

如需验证请求来自正版 Android 设备,而不是模拟器或其他仿冒设备的代码,请使用 Google Play Integrity API

广告欺诈

在此情况下,您的应用会检查用户在应用中的展示和操作是否真实且可验证。

建议使用的标识符:广告 ID

为什么这样建议?

根据 Google Play 开发者内容政策,在广告用例中使用广告 ID 是强制性要求,因为用户可以重置广告 ID。

数字版权管理 (DRM)

在此情况下,您的应用希望保护对知识产权或付费内容的欺诈性访问。

推荐使用的标识符:使用 FID 或 GUID 会强制用户重新安装应用以规避内容限制,这足以让大多数用户望而却步。如果这样的保护还不够,还可以利用 Android 提供的 DRM API 限制对内容的访问,包括针对每个 APK 的标识符、Widevine ID。

用户偏好设置

在这种情况下,您的应用会在应用上保存每个设备的用户状态,尤其是对于未登录的用户。您可以将此状态转移到同一设备上使用同一密钥签名的其他应用。

建议使用的标识符:FID 或 GUID

为什么这样建议?

不建议在重新安装后保留信息,因为用户可能想要通过重新安装应用来重置偏好设置。