3. 设备端指纹采集:IMEI/IDFA/AAID、MAC地址、IP地址、User-Agent、屏幕分辨率与DPI

设备指纹的采集,说白了就是给每个设备拍一张「身份证照片」。这张照片拍得好不好,直接决定了后续风控模型能不能认准人。我做了这么多年安全,见过太多因为采集不全或者采集错误导致误杀、漏杀的案例。

今天咱们就把这些核心采集项一个一个拆开看。每个字段怎么拿、有什么坑、在Android和iOS上有什么区别,我都会结合项目经验讲清楚。

3.1 设备标识符:IMEI / IDFA / AAID

设备标识符是指纹里最核心的部分。但不同系统、不同版本,获取方式天差地别。

3.1.1 IMEI(国际移动设备识别码)

IMEI是GSM网络的设备唯一编号,相当于手机的「身份证号」。在Android 10之前,获取IMEI相对容易,但之后权限收紧得非常厉害。

⚠️ 重要提醒: Android 10+ 无法通过常规API获取IMEI。即使声明了READ_PHONE_STATE权限,系统也会返回空值或抛出异常。这是合规红线,不要试图用反射或隐藏API绕过。

我曾经在一个金融项目中,客户坚持要采集IMEI做风控。结果上线后发现Android 10以上设备全部采集失败,导致大量用户被判定为「新设备」触发二次验证。后来我们改用了AAID + 设备特征组合的方案,才解决了这个问题。

iOS上IMEI从iOS 5开始就被完全屏蔽了,开发者根本拿不到。所以如果你做跨平台方案,千万别把IMEI当成必选项。

3.1.2 IDFA(广告标识符)

IDFA是iOS上的广告追踪标识符。用户可以在设置里「限制广告追踪」或者「重置IDFA」,所以它不是一个稳定的标识。

iOS 14之后,获取IDFA需要弹出App Tracking Transparency(ATT)弹窗,用户拒绝就返回全零。我见过一个电商App,因为没处理好ATT授权,导致70%的iOS用户IDFA为空,风控模型直接崩了。

💡 我的建议: 不要把IDFA作为唯一标识。把它当成一个辅助信号,配合Keychain存储的UUID一起用。用户重置IDFA后,可以通过设备特征匹配来识别。

3.1.3 AAID(Android广告标识符)

AAID是Google Play服务提供的广告标识,Android设备基本都支持。用户可以重置,但不会像IDFA那样频繁变化。

获取AAID需要Google Play服务,国内很多定制ROM可能没有。我遇到过某国产手机厂商把Google Play服务阉割了,AAID返回空。这种情况下,我们只能退回到用设备特征组合生成指纹。

标识符 平台 稳定性 获取难度 备注
IMEI Android 高 高(Android 10+受限) 合规风险大,建议放弃
IDFA iOS 中(可重置) 中(需ATT授权) 用户拒绝后为空
AAID Android 中(可重置) 低 依赖Google Play服务

3.2 网络层指纹:MAC地址与IP地址

网络层的两个字段,看似简单,实则暗坑无数。

3.2.1 MAC地址

MAC地址是网卡的物理地址,理论上全球唯一。但现实很骨感。

Android 6.0之后,系统API返回的是随机MAC地址(私有MAC)。Android 10之后,非系统应用根本拿不到真实MAC。iOS从iOS 7开始就返回02:00:00:00:00:00这种固定值。

我记得有个做WiFi探针的公司,想通过采集手机MAC来识别用户。结果发现Android 10以上的设备,每次扫描返回的MAC都不一样。他们以为是设备坏了,查了半天才发现是系统行为。

核心结论: MAC地址在现代移动端已经基本失去指纹价值。如果你还在用它做唯一标识,赶紧改方案。

3.2.2 IP地址

IP地址变化太频繁了。用户从WiFi切到4G,IP就变了。甚至同一个WiFi下,DHCP租约到期也可能变。

但IP地址在风控里依然有用——不是用来标识设备,而是用来做地理位置校验和代理检测。比如一个设备指纹声称在北京,但IP显示在洛杉矶,那大概率是代理。

我处理过一个刷单案例:攻击者用同一台设备,通过切换代理IP来模拟不同地区的用户。我们通过IP的ASN(自治系统号)和时区信息,发现这些IP都来自同一个数据中心,直接判定为异常。

3.3 应用层指纹:User-Agent

User-Agent(UA)是浏览器或App在HTTP请求中携带的标识字符串。它包含操作系统、浏览器版本、设备型号等信息。

UA的格式在不同平台上差异很大。Web端最复杂,移动端相对统一。但UA是可以伪造的,很多爬虫工具都会修改UA。

我建议把UA当成一个辅助信号,而不是主要指纹。你可以从UA里提取出操作系统版本、浏览器内核、设备型号等结构化信息,然后跟其他字段做交叉验证。

// 一个典型的移动端UA
Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) 
AppleWebKit/605.1.15 (KHTML, like Gecko) 
Version/16.0 Mobile/15E148 Safari/604.1

// 提取关键信息
OS: iOS 16.0
Browser: Safari 16.0
Device: iPhone
Engine: WebKit 605.1.15
💡 避坑指南: 不要直接拿UA字符串做哈希。因为UA里包含版本号,用户升级系统后UA变了,指纹就失效了。正确的做法是提取关键字段,比如只取操作系统主版本号和浏览器内核。

3.4 硬件特征:屏幕分辨率与DPI

屏幕分辨率和DPI是硬件指纹里比较稳定的字段。用户不会频繁换屏幕,而且不同型号的设备,这两个值的组合通常是唯一的。

但这里有个坑:分辨率受系统UI缩放影响。比如iPhone 14 Pro Max的实际分辨率是2796x1290,但系统UI缩放后,逻辑分辨率可能是430x932。你采集的时候要区分是物理分辨率还是逻辑分辨率。

DPI(每英寸像素数)也是一个重要指标。两个设备可能有相同的分辨率,但屏幕尺寸不同,DPI就不同。比如5.5寸的1080P和6.5寸的1080P,DPI差了将近20%。

设备 物理分辨率 逻辑分辨率 DPI 屏幕尺寸
iPhone 14 Pro Max 2796x1290 430x932 460 6.7寸
Samsung S23 Ultra 3088x1440 412x915 500 6.8寸
Xiaomi 13 Pro 3200x1440 360x780 522 6.73寸

你看,这三个设备的物理分辨率都不一样,DPI也不同。组合起来就是一个很强的指纹特征。

3.5 指纹采集的整体架构

说了这么多单个字段,咱们来看看它们怎么组合成一个完整的指纹采集流程。

设备指纹采集架构图 指纹采集SDK 设备标识符采集 网络层采集 硬件特征采集 IMEI / AAID IDFA / IDFV MAC地址 IP地址 屏幕分辨率 DPI 数据清洗 → 字段标准化 → 异常值过滤 特征哈希 → 指纹ID生成 设备指纹(Fingerprint) 注意:不同平台、不同系统版本,采集策略需要动态调整。Android 10+ 放弃IMEI,iOS 14+ 处理ATT授权。

这个架构图展示了完整的采集流程。从SDK入口开始,分三条线采集设备标识符、网络层和硬件特征。采集到的原始数据经过清洗和标准化,最后生成唯一的设备指纹。

嗯,这里要注意:每个字段的采集都要做异常处理。比如获取AAID时Google Play服务不可用,要能优雅降级到备用方案。我见过一个App,因为AAID获取失败直接崩溃,用户反馈差到爆。

3.6 采集策略总结

最后总结一下我的个人经验:

  • 优先使用AAID和IDFA,但要做好用户重置和授权拒绝的预案
  • IMEI能不用就不用,合规风险太大,而且Android 10以上基本拿不到
  • MAC地址已经废了,别在上面浪费时间
  • IP地址用来做辅助校验,别用来做唯一标识
  • 屏幕分辨率和DPI是稳定信号,但要注意区分物理和逻辑分辨率
  • 所有字段都要做异常处理,采集失败不能影响用户体验

你想想看,如果这些字段都采集对了,组合起来的指纹稳定性会非常高。我做过一个测试,在100万台设备上,仅用分辨率+DPI+AAID+UA这四个字段,就能区分出99.7%的设备。剩下的0.3%是同一型号、同一批次、同一网络环境的设备,这种场景下需要引入更多行为特征才能区分。