唯一标识符最佳做法

本文提供了根据用例为应用选择合适标识符的指导。

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

    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,而不是级别较低的 NetworkInterfacegetifaddrs() 或 Netlink 套接字等 API。例如,如果某个应用需要获取有关当前路线的最新信息,则可以使用 ConnectivityManager.registerNetworkCallback() 监听网络变化并调用网络的关联 LinkProperties.getRoutes() 来获取此类信息。

标识符特性

Android 操作系统提供了多种具有不同行为特性的 ID。您应该使用何种 ID 取决于以下特性适合您用例的程度。然而,这些特性还涉及到隐私权,因此您必须要了解这些特性彼此之间是如何互动的。

范围

标识符作用域说明了哪些系统可以访问标识符。Android 标识符的作用域一般分为三种:

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

向标识符授予的作用域越大,其作跟踪用途的风险就越大。相反,如果标识符只能由单一应用实例访问,就无法用于跨不同应用的事务跟踪设备。

重置性与持久性

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

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

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

唯一性

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

一般而言,您可以将用户账号标识符视为具有唯一性。也就是说,每个设备/账号组合都有一个唯一 ID。另一方面,标识符在某一群体内的唯一性越低,隐私保护效果就越好,因为它用于跟踪单个用户的有用性会降低。

完整性保护和不可否认性

您可以使用难以仿冒或重播的标识符证明关联的设备或账号具有某些属性。例如,您可以证明设备并非被垃圾内容发布者使用的虚拟设备。难以仿冒的标识符还能提供不可否认性。如果设备用密钥对一条消息进行了签名,就难以辩称这条消息是由他人的设备发出的。不可否认性可能是用户想要的(例如在验证身份时),也可能是不希望的属性(例如当用户发送后悔的消息时)。

常见用例和适用的标识符

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

账号

运营商状态

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

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

为什么这样建议?

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

移动设备订阅状态

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

推荐使用的标识符Subscription 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 开始,无论应用的目标 API 级别如何,Android 都进一步限制了通过 getIccId() API 访问 ICCID 的权限。受影响的应用应改为使用订阅 ID。

单点登录

在这种情况下,您的应用会提供单点登录体验,让用户能够将现有账号与贵组织相关联。

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

为什么这样建议?

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

广告

Targeting

在这种情况下,您的应用会根据用户的兴趣构建个人资料,以便向用户展示更相关的广告。

建议使用的标识符:如果您的应用使用 ID 投放广告,并且上传或发布到 Google Play,则该 ID 必须是广告 ID。

为什么这样建议?

这是一种与广告有关的用例,需要使用在贵组织的不同应用中均可用的 ID,因此使用广告 ID 是最合适的解决方案。按照 Google Play 开发者内容政策,在广告用例中使用广告 ID 是强制性要求,因为用户可以对其进行重置。

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

测量

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

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

为什么这样建议?

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

转化次数

在此情况下,您需要通过跟踪转化情况来确认营销策略是否成功。

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

为什么这样建议?

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

再营销

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

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

为什么这样建议?

这是一个与广告相关的用例,可能需要一个可在贵组织的不同应用中使用的 ID,因此使用广告 ID 是最合适的解决方案。按照 Google Play 开发者内容政策,在广告用例中使用广告 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 是强制性要求,因为用户可以对其进行重置。

数字版权管理 (DRM)

在这种情况下,您的应用想要保护对知识产权或付费内容的欺诈性访问。

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

用户偏好设置

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

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

为什么这样建议?

不建议让信息在重新安装后依然存在,因为用户可能想通过重新安装应用来重置其偏好设置。