HarmonyOS 鸿蒙NEXT中拿设备指纹目前有哪些方法?

HarmonyOS 鸿蒙NEXT中拿设备指纹目前有哪些方法? 请教各位大佬,如何在鸿蒙NEXT设备上获得设备唯一标识?(设备指纹/浏览器指纹)
IMEI、MAC地址不让取,OAID等又不够稳定,我现在临时折中解决方法是应用首次启动时生成并存储,不知道有没有更好的方法……

13 回复

【解决方案】

开发者您好,

常见设备的标识有OAID、ODID、AAID、UDID等,定义和用途如下:

  • OAID(开放匿名设备标识符)一种非永久性设备标识符,基于OAID,可在保护用户个人数据隐私安全的前提下,媒体App、广告平台、三方监测平台等开发者,可获取设备上的OAID,进行个性化广告推荐或广告转化归因分析。
  • ODID(开发者匿名设备标识符):用于识别同一设备上运行的同一个开发者的应用,标识应用身份。帮助开发者更好地理解用户在不同应用间的行为,从而提供更个性化的服务和推荐。
  • AAID(应用匿名标识符):标识应用的身份,主要用于应用的消息推送。
  • UDID(设备唯一标识符):标识设备的属性,可作为设备唯一识别码。

综上所述,只有UDID才能作为设备的唯一标识符,不会随设备重置或应用卸载而发生变化,但UDID只允许系统应用及企业应用申请特殊权限才能获取。当前设备重置时还无法保证标识符不发生改变,但有方案可以实现应用卸载时标识符不发生改变。

为了保证即使在应用卸载后仍能有效的确保获取的设备标识符不发生变化,间接达到“唯一标识符”的目的,华为提供了关键资产存储服务,开发者可以将设备标识符放在Asset里,设置IS_PERSISTENT为true,实现在应用卸载时保留关键资产,达到标识符不清除的效果。如获取ODID后配合使用Asset Store Kit能力,保持ODID不变的效果。

说明:如果要设置IS_PERSISTENT属性,需要申请ohos.permission.STORE_PERSISTENT_DATA权限。

示例代码如下:

import { asset } from '@kit.AssetStoreKit';
import util from '@ohos.util';
import { deviceInfo } from '@kit.BasicServicesKit';

function stringToArray(str: string): Uint8Array {
  let textEncoder = new util.TextEncoder();
  return textEncoder.encodeInto(str);
}

function setAttr(id: string) {
  let attr: asset.AssetMap = new Map();
  attr.set(asset.Tag.SECRET, stringToArray(id));
  attr.set(asset.Tag.ALIAS, stringToArray('demo_device_id'));
  attr.set(asset.Tag.IS_PERSISTENT, true);
  try {
    asset.add(attr).then(() => {
      console.info(`Asset added successfully.`);
    }).catch(() => {
      console.error(`Failed to add Asset.`);
    });
  } catch (error) {
    console.error(`Failed to add Asset.`);
  }
}

function arrayToString(arr: Uint8Array): string {
  let textDecoder = util.TextDecoder.create("utf-8", { ignoreBOM: true });
  let str = textDecoder.decodeToString(new Uint8Array(arr));
  return str;
}

async function getAttr(): Promise<string> {
  let query: asset.AssetMap = new Map();
  query.set(asset.Tag.ALIAS, stringToArray('demo_device_id')); // 指定了关键资产别名,最多查询到一条满足条件的关键资产
  query.set(asset.Tag.RETURN_TYPE, asset.ReturnType.ALL); // 此处表示需要返回关键资产的所有信息,即属性+明文
  try {
    const res: Array<asset.AssetMap> = await asset.query(query);
    // 解析密钥
    let secret: Uint8Array = res[0].get(asset.Tag.SECRET) as Uint8Array;
    // 将uint8array解析为字符串
    let secretStr: string = arrayToString(secret);
    return secretStr;
  } catch (error) {
    console.error(`Failed to query Asset.`);
    return '';
  }
}

@Entry
@Component
struct AttrTest {
  @State Odid: string = '';

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Button('获取设备ODID').onClick(async () => {
        let deviceId: string = await getAttr();
        if (deviceId === undefined || deviceId === null || deviceId.length === 0) {
          deviceId = deviceInfo.ODID;
          setAttr(deviceId);
        }
        this.Odid = deviceId;
        console.info('设备ODID为:' + deviceId);
      })
        .width('40%')
        .margin(20)
        .borderRadius('50%')

      Text(`${this.Odid}`)
    }
    .height('100%')
    .width('100%')
  }
}

更多关于HarmonyOS 鸿蒙NEXT中拿设备指纹目前有哪些方法?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


UDID(设备唯一标识符):标识设备的属性,可作为设备唯一识别码。UDID只允许系统应用及企业应用申请特殊权限才能获取。

你好,参考 【HarmonyOS NEXT】获取卸载APP后不变的设备ID 实现。

[@ohos.security.asset (关键资产存储服务)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-asset-V5): 关键资产存储服务提供了用户短敏感数据的安全存储及管理能力。其中,短敏感数据可以是密码类(账号/密码)、Token类(应用凭据)、也可以是 uuid。

有一个特殊属性 IS_PERSISTENT,该特性可实现,在应用卸载时保留关键资产,利用该特性,可以随机生成一个32位的uuid,存储到ohos.security.asset中。

HarmonyOS NEXT(尤其是面向应用市场发布的三方应用) 环境下,目前没有官方支持的“设备唯一标识”方案能够达到过去 Android IMEI、MAC 地址那种永久且全局唯一的效果。华为出于隐私保护已经限制了这类能力。

如果你的目标是做:

  • 风控
  • 防刷
  • 账号设备绑定
  • 浏览器指纹
  • 设备识别

建议按下面的优先级选择。


方案1:应用首次启动生成 UUID(推荐)

这其实已经是目前业界最主流的方案。

import { util } from '@kit.ArkTS'

let deviceId = util.generateRandomUUID()

生成后存入:

  • Preferences
  • Database
  • Asset Store(推荐)

优点:

  • 不需要权限
  • 不受系统限制
  • AppGallery审核不会卡

缺点:

  • 卸载重装会丢失

方案2:Asset Store 持久化 UUID(最推荐)

HarmonyOS NEXT 提供了:

@kit.AssetStoreKit

类似 iOS Keychain。

利用 Asset 的持久化能力,可以实现:

  • 卸载 App 后仍然保留
  • 重装后重新读取
  • 不需要 OAID 权限

很多 HarmonyOS 开发者目前都采用:

首次启动
↓
生成 UUID
↓
存入 AssetStore
(IS_PERSISTENT)
↓
以后一直读取

这种方案实际上已经成为 HarmonyOS NEXT 上最接近“设备ID”的实现方式。


方案3:OAID(广告标识)

如果你的业务允许申请广告标识权限:

ohos.permission.APP_TRACKING_CONSENT

可以获取:

OAID

特点:

  • 同一设备多个 App 获取到一致
  • 用户可重置
  • 用户关闭跟踪后返回全0
  • 需要弹授权框

因此:

❌ 不适合做设备唯一标识

更适合:

  • 广告归因
  • 营销统计

方案4:AAID

AAID 是应用实例标识。

特点:

  • 同一个应用唯一
  • 卸载重装会变
  • 清数据会变

适合作为:

安装实例ID

不适合作为设备ID。


方案5:ODID

ODID 是开发者级设备标识。

特点:

  • 同一开发者的多个应用可关联
  • 全部应用卸载后可能变化

适合:

  • 同开发者应用体系

不适合:

  • 强设备绑定

浏览器指纹能不能做?

理论上可以。

例如收集:

设备型号
系统版本
屏幕尺寸
DPI
语言
时区
字体
WebGL信息
Canvas特征
UserAgent

生成:

SHA256(...)

形成 Fingerprint。

但有几个问题:

  1. HarmonyOS WebView 对部分硬件信息有限制
  2. 浏览器升级后可能变化
  3. 同型号设备碰撞率较高
  4. AppGallery审核对跨应用追踪比较敏感

所以只能作为:

辅助风控因子

不能当唯一设备ID。


如果是企业级风控系统

目前比较稳妥的做法是:

设备UUID(AssetStore持久化)
+
账号ID
+
设备型号
+
系统版本
+
OAID(有权限时)
+
网络特征

服务端生成:

Device Fingerprint

而不是依赖某一个系统ID。


结论

对于 HarmonyOS NEXT 三方应用:

❌ IMEI 不可获取

❌ MAC 地址不可获取

❌ UDID 仅系统应用可用

实际项目中最推荐的是:

AssetStore持久化UUID
+
服务端设备指纹

这也是目前鸿蒙生态里最接近“设备唯一标识”的通用方案。

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

普通三方应用不建议再按“拿一个永久设备指纹”的思路设计。IMEI、MAC 这类强设备标识已经受限,UDID 也不是普通应用随便可取的能力;这不是少了一个 API,而是隐私合规方向变了:系统不希望应用绕过用户重置和授权,长期追踪同一台设备。

可以按业务目标选方案:广告归因用 OAID;同一开发者下多应用识别可看 ODID;推送、应用内身份可结合 AAID 或账号体系。如果只是想给未登录用户一个稳定本地标识,比较稳的是首次启动生成随机 UUID,存入首选项或 Asset Store;如果需要卸载后仍尽量保留,可以评估 Asset Store 的持久化能力,并按要求申请对应权限。

不要用浏览器指纹、字体列表、UA、传感器等拼装“影子指纹”,审核和合规风险都高。参考来源:开放匿名标识服务、Asset Store Kit、HarmonyOS 隐私与权限规范。

试试集成三方SDK呢,好像有一个叫OAID什么的吧

参考下:《设备标识使用推荐》
有个《应用设备状态检测》,可以获取个DeviceToken,应用在无法获取到持久化设备标识的情况下也可以对设备的应用状态进行记录和查询。

的确,目前传统硬件标识如IMEI、MAC地址等已禁止普通应用直接获取。给你一个较可靠的持久化标识方案。你可以在应用首次启动时生成一个自定义标识符(如UUID),并利用Asset Store Kit将其存储为“关键资产”,设置IS_PERSISTENT属性为true。即使应用卸载,该标识符仍会保留在设备上,重新安装后可读取同一标识符,实现设备绑定效果。使用此功能需要申请ohos.permission.STORE_PERSISTENT_DATA权限。

具体步骤如下:

权限申请:在module.json5中声明ohos.permission.STORE_PERSISTENT_DATA权限,并确保用户授权。

标识符生成与存储:应用首次启动时生成随机唯一标识符,通过Asset Store Kit的接口将其存入关键资产,并设置IS_PERSISTENT为true。

后续读取:每次启动应用时尝试从关键资产中读取该标识符,若存在则直接使用,否则重新生成并存储。

应该都是自己生成随机数,然后通过 Asset Store Kit(关键资产存储服务)去存储,这样保证设备ID不会丢失; 主要其他都不符合;

常见设备的标识有OAID、ODID、AAID、UDID等,定义和用途如下:

  • OAID(开放匿名设备标识符)一种非永久性设备标识符,基于OAID,可在保护用户个人数据隐私安全的前提下,媒体App、广告平台、三方监测平台等开发者,可获取设备上的OAID,进行个性化广告推荐或广告转化归因分析。
  • ODID(开发者匿名设备标识符):用于识别同一设备上运行的同一个开发者的应用,标识应用身份。帮助开发者更好地理解用户在不同应用间的行为,从而提供更个性化的服务和推荐。
  • AAID(应用匿名标识符):标识应用的身份,主要用于应用的消息推送。
  • UDID(设备唯一标识符):标识设备的属性,可作为设备唯一识别码。
    只有UDID才能作为设备的唯一标识符,不会随设备重置或应用卸载而发生变化,但UDID只允许系统应用及企业应用申请特殊权限才能获取。

在HarmonyOS NEXT中获取设备指纹的方法包括:

  • 使用DeviceInfoKitgetDeviceId获取设备唯一标识(UUID)。
  • 通过@ohos.deviceInfo模块的GetDeviceUdid获取UDID(需申请ohos.permission.GET_DEVICE_UDID权限)。
  • 调用deviceAttestation相关接口获取设备安全等级标识。
  • 利用Settings.getUri读取系统属性(如ro.serialno),需系统级权限。

HarmonyOS NEXT 中获取设备指纹目前官方推荐且可持续使用的方式是 OAID(开放匿名设备标识符),通过 @ohos.identifier 模块获取。

需要声明权限 ohos.permission.APP_TRACKING_CONSENT,并在首次调用时引导用户授权。示例:

import identifier from '@ohos.identifier';

async function getOAID() {
  try {
    let result = await identifier.getOAID();
    // result.oaid 即为 OAID 字符串
    console.info('OAID:', result.oaid);
  } catch (err) {
    console.error('获取OAID失败', err);
  }
}

OAID 在恢复出厂设置或用户重置广告追踪标识时会变化,稳定性弱于硬件标识,但已是当前系统对三方应用开放的唯一设备级标识。
你已有的“首次启动生成并存储”方案可以作为兜底:生成 UUID 后使用 HUKS 安全存储,与 OAID 组合使用,既能弥补 OAID 可能变化的问题,也符合隐私规范。

回到顶部